Używam bibliotek klienckich Apache HTTP Client i Jacksona w moim kliencie. Kiedy zakładać JSON do serwera pojawia się błąd:Jackson-> Jackson + HttpPost = "Nieprawidłowy średni bajt UTF-8", Ustawianie mime i kodowania
org.codehaus.jackson.JsonParseException: Invalid UTF-8 middle byte 0x65
at [Source: [email protected]; line: 1, column: 81]
Jeśli nie określa żadnych nagłówków niż otrzymuję invalid media type
, które ma sens.
Jeśli używam nagłówki skręcania i tym samym, serwer akceptuje go, więc myślę, że serwer jest OK (i tylko zbieg okoliczności, że to również za pomocą Jackson)
nich jest dokument; Mam ciężko kodowane jako Java dosłownym użyciu tylko 8 bitowe znaki w celu uniknięcia jakiegokolwiek innego miejsca do maglowania wydarzy
// "Stra\u00DFe" = "Straße"
static String TINY_UTF8_DOC = "[{ \"id\" : \"2\", \"fields\" : { \"subject\" : [{ \"name\" : \"subject\", \"value\" : \"Stra\u00DFe\" }] } }]";
Oto kod używam i komentarze z różnych prób:
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...
Inne dziwne rzeczy zauważyłem:
- przez pewien czas ten zachowywał się inaczej na Eclipse na Mac vs. prowadzenie .jar na Linux; Wyraźnie jest to symptom kodowania lub dekodowania specyficznego dla platformy, ale nie wiem gdzie. Jak na ironię, złamał po ustawieniu Eclipse, aby traktował kod jako UTF-8 (w porównaniu z ASCII). Podejrzewam, że jest to ważna wskazówka, ale nie wiem, gdzie to pasuje.
- Widziałem czasy, gdy zamiast 2 bajtów w strumieniu są 4 bajty, chociaż może to być inny problem z kodowaniem podczas zapisywania na dysk, chociaż specjalnie ustawiłem kodowanie UTF-8 na pliku IO
- Kiedy spójrz na element string w debugerze, widzę bajty, ale znak 8-bitowy jest liczbą ujemną. Gdy przejdziesz przez matematykę "Dwa", to wciąż jest to poprawny kodowy kod Unicode, więc nominalnie OK, zakładając, że httpclient nie jest błędny.
Naprawdę z pomysłów, i jak powiedziałem, działa z lokami, więc myślę, że serwer jest w porządku.
Edit:
curl działa podczas księgowania do serwera, ale nie mogę udostępnić kod serwera. Zwrócono uwagę, że skoro curl nie jest napisany w Javie, więc być może zachowuje się inaczej, dlatego kod serwera nadal może być podejrzany.
W ramach dalszego testu poniższy kod: NOT korzysta z biblioteki httpclient Apache i działa przy wysyłaniu wiadomości na serwer. Dowodzi to, że serwer jest w porządku i nadal jest coś nie tak z tym, jak używam biblioteki Apache po stronie klienta (lub może to błąd).
dla apache-httpclient kod, który działa:
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);
}
}
Jest tu problem; tutaj, 'ß' jest' \ u00DF' jako sekwencja ze znakiem UTF-16, ale czytasz _byte_ 0x65; jakie jest twoje źródło? – fge
Ten błąd UTF-8 zostanie wygenerowany tylko wtedy, gdy próbujesz odczytać coś jako UTF-8, który nie jest UTF-8. UTF-8 działa poprzez dopełnienie pierwszego bajtu o 1 w górnej stronie, aby wskazać liczbę bajtów do odczytania dla postaci. Reszta bajtów musi zaczynać się od "10", która działa jak bity kontrolne, inaczej wie, że parsowanie jest problemem. W twoim przypadku masz bajt, który ma 1 po lewej stronie, ale za mało bajtów, aby spełnić podany numer. Krótko mówiąc, domyślam się, że twój klient nie wysyła w ogóle UTF-8. Odsyłacz: http://en.wikipedia.org/wiki/UTF-8 – CodeChimp
Czy możesz spróbować podwoić ukośnik odwrotny przed 'u00DF', aby JSON odczytał" \ u00DF "? – fge