2014-05-09 3 views
8

저는 클라이언트에서 Apache HTTP 클라이언트 라이브러리와 Jackson을 사용하고 있습니다. 내가 서버에 JSON을 게시 할 때 나는 오류를 얻을 :Jackson-> Jackson + HttpPost = "유효하지 않은 UTF-8 중간 바이트", MIME 및 인코딩 설정

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

내가 의미가있는 invalid media type을 얻을 것보다 어떤 헤더를 설정하지 않은 경우.

나는 컬과 같은 헤더를 사용하는 경우, 서버는 그것을 받아, 그래서 서버가 OK (그리고 잭슨을 사용하고 있음을 단지 우연의 일치)

이 문서입니다 생각; 열심히 여기

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

내가 사용하고 코드의 일이 맹 글링을 위해 다른 장소를 피하기 위해 단지 8 비트 문자를 사용하여 리터럴 자바로 코딩하고, 한 다양한 시도와 의견 :

내가 눈치 챘을
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... 

다른 이상한 일이 리눅스에서의 .jar을 실행하는 대 맥에서 이클립스에서 다르게 행동 잠시 동안

  • ; 플랫폼 별 인코딩 또는 디코딩의 증상 인 것은 분명하지만 어디서부터인지 모르겠습니다. 아이러니하게도 일 때 Eclipse를 코드를 UTF-8 (대 ASCII)로 처리하도록 설정할 때 이것이 중요한 단서로 의심 스럽지만 확실한 곳은 아닌 것 같습니다.
  • 대신 2 바이트 스트림에서 4 바이트있을 때 디스크에 기록 할 때 내가 특별히 IO
  • 파일을 UTF-8로 설정 되었더라도이, 다른 인코딩 문제가되었을 수도 있지만 내가 번 본 적이 언제 디버거에서 문자열 엔터티를 보면 바이트가 표시되지만 8 비트 문자는 음수입니다. Two 's Compliment 수학을 실행하면 올바른 Unicode 코드 포인트가됩니다. 따라서 httpclient가 버그가 없다고 가정하면 정상적으로 OK입니다.

정말 아이디어가 부족합니다. 말했듯이 말풍선과 작동하기 때문에 서버가 정상이라고 생각합니다.

편집 : 서버에 게시 할 때

컬은 작동하지만 서버 코드를 공유 할 수 없습니다. curl은 Java로 작성되지 않았기 때문에 다르게 동작하므로 서버 코드가 여전히 의심 될 수 있다는 지적이있었습니다.

다음 코드는 이 아니며은 Apache httpclient 라이브러리를 사용하며 서버에 게시 할 때 작동합니다. 이것은 서버가 훌륭하다는 것을 증명하고, 클라이언트 측에서 아파치 라이브러리를 사용하는 방법에 여전히 문제가 있습니다 (또는 버그 일 수도 있습니다). 하지

비 아파치 HttpClient를 코드, 작업 :

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); 
    } 
} 
+1

여기에 문제가있다; 여기에서'ß'는 이스케이프 된 UTF-16 시퀀스로'\ u00DF'이지만 _byte_ 0x65를 읽습니다. 당신의 근원은 무엇입니까? – fge

+0

UTF-8이 아닌 UTF-8로 읽으려는 경우에만 UTF-8 오류가 생성됩니다. UTF-8은 첫 번째 바이트를 상위 비트 측면에 1로 채워서 문자를 읽는 데 필요한 바이트 수를 나타냅니다. 나머지 바이트는 '10'으로 시작해야하는데, 체크 비트와 같은 종류의 동작입니다. 그렇지 않으면 구문 분석에 문제가 있음을 알 수 있습니다. 귀하의 경우에는 왼쪽에 1을 가지고 있지만 지정된 숫자를 만족시키기에 충분한 바이트가없는 바이트가 있습니다. 간단히 말해 클라이언트가 UTF-8을 보내지 않고있는 것 같습니다. 참조 : http://en.wikipedia.org/wiki/UTF-8 – CodeChimp

+0

JSON에서 "\ u00DF"를 읽을 수 있도록 'u00DF'이전에 백 슬래시를 두 번 사용해 볼 수 있습니까? – fge

답변

12

문제가 HttpClient를의 StringEntity 생성자에 대한 ContentType 매개 변수가 생성되는 방법입니다 것 같습니다.

ContentType.APPLICATION_JSON 상수를 매개 변수로 사용하면 ("application/json; charset = utf-8"MIME 유형에 해당) 모든 것이 작동합니다.여기

클라이언트에 다시 요청을 메아리 공공 HTTP 서비스에 JSON 문자열을 게시 예입니다

public class HttpClientEncoding { 

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

    public static void main(String[] args) throws IOException { 
     HttpClient httpClient = new DefaultHttpClient(); 
     HttpPost post = new HttpPost("http://httpbin.org/post"); 
     StringEntity entity = new StringEntity(TINY_UTF8_DOC, ContentType.APPLICATION_JSON); 
     //StringEntity entity = new StringEntity(TINY_UTF8_DOC, ContentType.create("application/json; charset=utf-8")); 
     post.setEntity(entity); 
     HttpResponse response = httpClient.execute(post); 
     String result = EntityUtils.toString(response.getEntity()); 
     System.out.println(result); 
     ObjectMapper mapper = new ObjectMapper(); 
     JsonNode node = mapper.readValue(result, JsonNode.class); 
     System.out.println(node.get("json").get(0).get("fields").get("subject").get(0).get("value").asText()); 
    } 
} 

출력 :

{ 
    "origin": "46.9.77.167", 
    "url": "http://httpbin.org/post", 
    "args": {}, 
    "data": "[{ \"id\" : \"2\", \"fields\" : { \"subject\" : [{ \"name\" : \"subject\", \"value\" : \"Stra\u00dfe\" }] } }]", 
    "files": {}, 
    "form": {}, 
    "headers": { 
    "Content-Length": "90", 
    "User-Agent": "Apache-HttpClient/4.3.3 (java 1.5)", 
    "Host": "httpbin.org", 
    "Connection": "close", 
    "X-Request-Id": "c02864cc-a1d6-434c-9cff-1f6187ceb080", 
    "Content-Type": "application/json; charset=UTF-8" 
    }, 
    "json": [ 
    { 
     "id": "2", 
     "fields": { 
     "subject": [ 
      { 
      "value": "Stra\u00dfe", 
      "name": "subject" 
      } 
     ] 
     } 
    } 
    ] 
} 
Straße 
+2

고맙습니다. 고쳐 주셔서 감사합니다. vs-strings는 최신 버전이지만 온라인에서 찾은 예제는 더 오래되었습니다. httpbin.org 사이트에 대한 링크와이 lib를 처음 접했을 때의 예를 읽어 주신 것에 대해 감사드립니다. –

+0

'ContentType.APPLICATION_JSON' 두 번째 인자로 StringEntity를 만들려고했거나 HttpPost 객체에 헤더를 추가하려고했습니다. 다음과 같이'request.addHeader ("Content-Type", ContentType.APPLICATION_JSON.toString()); '. 하지만 내 메시지에 'é', 'è'또는 'ô'가 포함 된 경우 같은 오류 "JsonMappingException : 잘못된 UTF-8 중간 바이트 0xZZ"가 계속 발생합니다. ZZ는 값에 따라 변경되는 16 진수 값입니다. – Alex

관련 문제