2013-08-11 9 views
8

Sto utilizzando il framework di jackson per il marshalling e l'unmarshalling dei dati tra JSON e Java. Tutto funziona bene, purché l'ingresso non contiene personaggi come:org.codehaus.jackson.JsonParseException: byte medio UTF-8 non valido 0xdf

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

Per i dati di input che ho provato:

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

così come:

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

e per tutto il tempo ho la stessa eccezione.

La mappatura dai dati JSON per oggetto entità Java è fatto tramite:

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

Ho anche eseguire una convalida dati JSON che funziona come previsto, anche con i caratteri di cui sopra.

Come devono essere gestiti tali dati?

UPDATE Queste sono le parti importanti della classe 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

Potresti fornirci anche il codice stringToStream? – Jk1

+0

Fonte aggiunta, grazie – 123456789

risposta

9

JSON disciplinare prevede che solo codifiche validi sono UTF-8, UTF-16 e UTF-32. Non è possibile utilizzare altre codifiche (come Latin-1). L'implementazione di stringToStream non imposta la codifica in modo esplicito, pertanto viene utilizzato il sistema predefinito. Ecco come hai ottenuto un flusso non uto. Nel passaggio successivo, Jakson sta tentando di analizzare il flusso utilizzando una delle codifiche UTF (ha un algoritmo di rilevamento integrato) e non riesce. Provare a impostare una codifica esplicita:

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

È già avuto una risposta, ma una domanda ovvia è: perché stai convertendo da un String a un flusso? Questa è una cosa inutile e inutile da fare, quindi basta passare la stringa così com'è. Questo rimuoverà anche il problema; Le stringhe non hanno codifica di per sé (ovvero: c'è solo una singola rappresentazione in memoria e non sono necessarie conversioni).

+0

Oh, grazie! Si sta facendo riferimento alla chiamata senza riarmo che può essere semplificata in: 'T entity = (T) m.readValue (jsonData, readableClass);' Ci sono ulteriori miglioramenti? – 123456789

+0

Durante la lettura di un file come stringa, è consigliabile utilizzare anche il 'InputStreamReader' di base, aggiungere usando' StringBuilder', anziché riga per riga. Oppure, se JSON Schema Validator è in grado di leggere da un 'Reader' o' InputStream', passa a quelli - potrebbe anche star usando Jackson sotto il cofano. – StaxMan

Problemi correlati