Jackson->Jackson + HttpPost = "Ungültige UTF-8-middle-byte", Einstellung Mime-Codierung

Bin ich mit dem Apache-HTTP-Client-libs und Jackson in meiner client. Wenn ich JSON auf dem server bekomme ich die Fehlermeldung:

org.codehaus.jackson.JsonParseException: Invalid UTF-8 middle byte 0x65
 at [Source: HttpInputOverHTTP@22a4ac95; line: 1, column: 81]

Wenn ich nicht alle Header, als ich bekommen invalid media type, was Sinn macht.

Wenn ich curl und den gleichen Header, die der server akzeptiert es, so denke ich, der server ist OK (und nur ein Zufall, dass es auch mit Jackson)

Diese ist das Dokument, ich habe hart codiert es als Java-literal mit nur 8-bit-Zeichen zu vermeiden, keine andere Stelle für mangeln passieren

//"Stra\u00DFe" = "Straße"
static String TINY_UTF8_DOC = "[{ \"id\" : \"2\", \"fields\" : { \"subject\" : [{ \"name\" : \"subject\", \"value\" : \"Stra\u00DFe\" }] } }]";

Hier ist der code, den ich benutzt habe, und die Kommentare mit den verschiedenen versuchen:

HttpClient httpClient = new DefaultHttpClient();
HttpPost post = new HttpPost( url );

//Attempt A
//post.setEntity(  new StringEntity( content )  );

//Attempt B
//post.setEntity(  new StringEntity( content )  );
//post.setHeader("Content-Type", "application/json; charset=utf-8");

//Attempt C
//post.setEntity(  new StringEntity( content, ContentType.create("application/json") )  );

//Attempt D
//post.setEntity(  new StringEntity( content, ContentType.create("application/json; charset=UTF-8") )  );

//Attempt F
//post.setEntity(  new StringEntity( content, ContentType.create("application/json; charset=utf-8") )  );

//Attempt G
//StringEntity params = new StringEntity( content );
//params.setContentType("application/json; charset=UTF-8");
//post.setEntity(params);

//And then send to server
HttpResponse response = httpClient.execute( post );
int code = response.getStatusLine().getStatusCode();
//...etc...

Andere seltsame Dinge, die ich bemerkt habe:

  • Für eine Weile diese verhielten sich anders auf Eclipse auf dem Mac vs laufen ein .jar unter Linux; klar, das ist ein symptom für Plattform-spezifische Codierung oder Decodierung, aber ich weiß nicht wo. Ironisch, dass brach wenn ich Eclipse zur Behandlung von code als UTF-8 (vs. ASCII -) ich vermute, dies ist ein wichtiger Anhaltspunkt, aber nicht sicher, wo es passt.
  • Ich habe Zeiten gesehen, wenn anstelle von 2 bytes gibt es noch 4 bytes in den stream, obwohl dies vielleicht ein anderes encoding problem beim schreiben auf die Festplatte, obwohl ich ausdrücklich die Einstellung UTF-8 Datei-E /a
  • Wenn ich mir den string Einheit im debugger sehe ich die bytes, aber die 8-bit-Zeichen ist eine negative Zahl. Wenn Sie laufen durch die Zwei s Kompliment Mathematik, ist es immer noch den korrekten Unicode code point, also nominell OK, vorausgesetzt, httpclient ist nicht buggy.

Wirklich die Ideen aus, und als ich sagte, es funktioniert mit curl, so dass ich denke, der server ist OK.

Edit:

curl funktioniert, wenn die Buchung auf dem server, aber ich kann nicht teilen Sie die server-code. Es wurde darauf hingewiesen, dass, da curl nicht in Java geschrieben, und so ist es vielleicht verhält sich anders, und daher der server-code könnte noch vermuten.

So, wie ein weiterer test, der code unten tut NICHT verwenden Sie die Apache-httpclient-Bibliothek, und funktioniert auch wenn die Buchung auf dem server. Dies beweist, dass der server in Ordnung ist und es gibt immer noch etwas falsch, wie ich mit der Apache-Bibliothek auf der client-Seite (oder vielleicht ist es auch buggy).

Nicht-apache-httpclient-code, der funktioniert:

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;

class PostUtf8 {
    static String POST_URL = "http://...";

    //\u00DF = LATIN SMALL LETTER SHARP S, looks like letter B
    static String TINY_UTF8_DOC = "[{ \"id\" : \"2\", \"fields\" : { \"subject\" : [{ \"name\" : \"subject\", \"value\" : \"Stra\u00DFe\" }] } }]";

    public static void main( String [] args ) throws Exception {
        System.out.println( "Posting to " + POST_URL );
        URL url = new URL( POST_URL );
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestProperty( "Content-Type", "application/json; charset=UTF-8" );
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        OutputStream sout = conn.getOutputStream();
        OutputStreamWriter wout = new OutputStreamWriter(sout, "UTF-8" );
        wout.write( TINY_UTF8_DOC );
        wout.flush();
        int result = conn.getResponseCode();
        System.out.println( "Result = " + result );
    }
}
  • Es gibt hier ein problem; hier ß ist \u00DF als ein entflohener UTF-16-Sequenz, sondern Sie Lesen byte 0x65, was ist deine Quelle?
  • Dass UTF-8-Fehler wird nur produziert, wenn Sie versuchen, etwas zu Lesen, als UTF-8, die nicht UTF-8. UTF-8 funktioniert durch die Polsterung wird das erste byte mit 1 ist in der high-bit-Seite, um anzugeben, wie viele bytes zu Lesen, die für den Charakter. Der rest des bytes haben, um mit zu beginnen '10', welche Art von Handlungen, wie check-bits, was es sonst kennt, es gibt ein problem Parsen. In Ihrem Fall haben Sie ein byte mit einer 1 in der linken Seite, aber nicht genug bytes nach erfüllen der angegebenen Nummer an. Lange Geschichte kurz, ich nehme an, dass dein client nicht senden von UTF-8 auf allen. Verweis: en.wikipedia.org/wiki/UTF-8
  • Können Sie versuchen und die doppelte backslash vor u00DF so, dass die JSON-liest "\u00DF"?
  • danke, ich bin damit einverstanden, es ist mis-encoded durch die Zeit wird es an den server, aber die Frage ist, wie/warum? Klar ich bin mis-mithilfe der client-libs irgendwie, aber alle Beispiele, die ich gesehen habe scheinen zu Folgen solchen mustern.
  • zu deinem ersten Kommentar, backslash u und dann 4-stellig ist der standard-Weg, um finden ein Uncode-code-point in Java, die Sie normalerweise würde nicht \uDF (2 Ziffern). Wie ich es verstehe, während in RAM, Java ist die Verwendung von UTF-16 (oder eine Variante) für Zeichen, und nur, wenn Sie Strom an/aus Dateien oder von anderen Prozessen funktioniert es verschieben auf UTF-8.
  • zu Ihrem zweiten Kommentar, putting 2 backslashes funktioniert, die ist cool, aber es ist ein workaround. Die real-Daten ich bin immer nicht kommen mag, dass es die richtigen UTF-8 (auf dem Weg), und gespeichert als eine richtige 16-bit-Java-Charakter einmal im Speicher. Ich benutzt das backslash-notation in meinem test nur. Ich kann also nicht einfach ersetzen \ mit \\, da gibt es keine backslashes bei der Eingabe. Wie ein hässlicher workaround, ich denke, ich könnte für jede > 7-bit-Zeichen und ersetzen Sie es mit einem umgekehrten Reihenfolge, aber ich sollte das wirklich nicht zu tun haben, dass die Bibliothek tun sollten (wenn Sie richtig verwendet und nicht buggy).
  • Gut, es gibt ein problem in der Art und Weise der JSON gelesen, wie es scheint. Wie wird es gelesen? Aus einer InputStream?
  • Ich bin mir ziemlich sicher, dass der server liest den stream richtig, es funktioniert, wenn ich curl.
  • Schaut sich um ich beschlossen, zu versuchen StringEscapeUtils.escapeJava und escapeJson von commons-lang3, sondern auch escape-Anführungszeichen, etc, also nicht ein guter workaround. Das muss doch eine einfache Sache, die ich falsch mache.
  • curl ist nicht Java... Kannst du die Java-code zu Lesen?
  • Kann ich nicht wirklich teilen, aber ich glaube, dass es Jackson, eine standard-Java-Bibliothek. Ich werde den ping-Entwickler, und wird nach meinem workaround unten.
  • Dies ist eine Problemumgehung für das problem. Ich bin nicht posting als Antwort, da ich nicht glaube, dass es der "richtige" Weg, es zu tun. String escapeUnicode( String inBuff ) { StringBuffer outBuff = new StringBuffer(); for ( int i = 0; i<inBuff.length(); i++ ) { char c = inBuff.charAt(i); int ic = c; if ( ic <= 127 ) { outBuff.append( c ); } else { outBuff.append( "\\u" ); outBuff.append( String.format("%04d", ic).toUpperCase() ); } } return new String( outBuff ); }
  • Siehe stackoverflow.com/questions/6352861/...

InformationsquelleAutor Mark Bennett | 2014-05-09
Schreibe einen Kommentar