2013-08-11 32 views
8

Tôi đang sử dụng khung công cụ jackson để marshaling và unmarshalling dữ liệu giữa JSON và Java. Tất cả mọi thứ hoạt động tốt, miễn là đầu vào không chứa bất kỳ ký tự như:org.codehaus.jackson.JsonParseException: byte trung gian UTF-8 không hợp lệ 0xdf

  • ö
  • ä
  • ü
  • Ö
  • Ä
  • Ü
  • ß

Đối với dữ liệu đầu vào tôi đã thử:

String jsonData = "{\"id\":1,\"street\":\"Straße\",\"number\":\"1c\",\"zipCode\":1111,\"city\":\"MyCity\"}"; 

cũng như:

String jsonData = "{\"id\":1,\"street\":\"Stra\u00DFe\",\"number\":\"1c\",\"zipCode\":1111,\"city\":\"MyCity\"}"; 

và tất cả các thời gian tôi nhận được cùng một ngoại lệ.

Các ánh xạ từ dữ liệu json để đối tượng java thực thể được thực hiện thông qua:

/* 
* Convert stream to data entity 
*/ 
ObjectMapper m = new ObjectMapper(); 
T entity = (T) m.readValue(stringToStream(jsonData), readableClass); 

Tôi cũng thực hiện một xác nhận dữ liệu json mà hoạt động như mong đợi, còn với các ký tự ở trên.

Dữ liệu đó nên được xử lý như thế nào?

CẬP NHẬT Đây là những phần quan trọng của lớp MessageBodyReader

@Override 
public T readFrom(Class<T> type, Type genericType, 
     Annotation[] annotations, MediaType mediaType, 
     MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 
     throws IOException, WebApplicationException { 

    final String jsonData = getStringFromInputStream(entityStream); 
    System.out.println(jsonData); 

    InputStream isSchema = new FileInputStream(jsonSchemaFile); 
    String jsonSchema = getStringFromInputStream(isSchema); 

    /* 
    * Perform JSON data validation against schema 
    */ 
    validateJsonData(jsonSchema, jsonData); 

    /* 
    * Convert stream to data entity 
    */ 
    ObjectMapper m = new ObjectMapper(); 
    T entity = (T) m.readValue(stringToStream(jsonData), readableClass); 

    return entity; 
} 

/** 
* Validate the given JSON data against the given JSON schema 
* 
* @param jsonSchema 
*   as String 
* @param jsonData 
*   as String 
* @throws MessageBodyReaderValidationException 
*    in case of an error during validation process 
*/ 
private void validateJsonData(final String jsonSchema, final String jsonData) 
     throws MessageBodyReaderValidationException { 
    try { 
     final JsonNode d = JsonLoader.fromString(jsonData); 
     final JsonNode s = JsonLoader.fromString(jsonSchema); 

     final JsonSchemaFactory factory = JsonSchemaFactory.byDefault(); 
     JsonValidator v = factory.getValidator(); 

     ProcessingReport report = v.validate(s, d); 
     System.out.println(report); 
     if (!report.toString().contains("success")) { 
      throw new MessageBodyReaderValidationException(
        report.toString()); 
     } 

    } catch (IOException e) { 
     throw new MessageBodyReaderValidationException(
       "Failed to validate json data", e); 
    } catch (ProcessingException e) { 
     throw new MessageBodyReaderValidationException(
       "Failed to validate json data", e); 
    } 
} 

/** 
* Taken from <a href= 
* "http://www.mkyong.com/java/how-to-convert-inputstream-to-string-in-java/" 
* >www.mkyong.com</a> 
* 
* @param is 
*   {@link InputStream} 
* @return Stream content as String 
*/ 
private String getStringFromInputStream(InputStream is) { 
    BufferedReader br = null; 
    StringBuilder sb = new StringBuilder(); 

    String line; 
    try { 

     br = new BufferedReader(new InputStreamReader(is)); 
     while ((line = br.readLine()) != null) { 
      sb.append(line); 
     } 

    } catch (IOException e) { 
     e.printStackTrace(); 
    } finally { 
     if (br != null) { 
      try { 
       br.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    return sb.toString(); 
} 

private InputStream stringToStream(final String str) { 
    return new ByteArrayInputStream(str.getBytes()); 
} 
+0

Bạn có thể vui lòng cung cấp cho chúng tôi mã stringToStream không? – Jk1

+0

Nguồn được thêm, thx – 123456789

Trả lời

9

JSON bang đặc điểm kỹ thuật, mà chỉ mã hóa hợp lệ là UTF-8, UTF-16 và UTF-32. Không có mã hóa nào khác (như Latin-1) có thể được sử dụng. Việc triển khai stringToStream của bạn không đặt mã hóa một cách rõ ràng, do đó, mặc định hệ thống được sử dụng. Đó là cách bạn có luồng không phải utf. Trong bước tiếp theo, Jakson đang cố gắng phân tích luồng bằng cách sử dụng một trong các mã hóa UTF (nó có thuật toán phát hiện được tích hợp sẵn) và không thành công. Hãy thử thiết lập một mã hóa rõ ràng:

new ByteArrayInputStream(str.getBytes("UTF-8")); 
1

Bạn đã có một câu trả lời, nhưng một câu hỏi rõ ràng ở đây là: tại sao bạn chuyển đổi từ một String đến một dòng? Đó là điều không cần thiết và lãng phí để làm - vì vậy chỉ cần vượt qua chuỗi như là. Điều này cũng sẽ loại bỏ vấn đề; Các chuỗi không có mã hóa trên mỗi giây (nghĩa là: chỉ có một biểu diễn trong bộ nhớ đơn và không cần chuyển đổi).

+0

Ồ, cảm ơn bạn! Bạn đang tham chiếu đến cuộc gọi unmarshalling có thể được đơn giản hóa thành: 'T entity = (T) m.readValue (jsonData, readableClass);' Có cải tiến nào khác không? – 123456789

+0

Khi đọc một tệp dưới dạng Chuỗi, cũng tốt hơn để sử dụng 'InputStreamReader' cơ bản, nối thêm bằng cách sử dụng' StringBuilder', thay vì dòng-by-line. Hoặc, nếu Trình xác thực lược đồ JSON có thể đọc từ một 'Reader' hoặc' InputStream', thì hãy vượt qua chúng - nó cũng có thể đang sử dụng Jackson dưới mui xe. – StaxMan

Các vấn đề liên quan