Sto cercando di utilizzare il parser Jackson Json (v2.5.2) per analizzare un documento json personalizzato che non è vero json e non riesco a capire come fallo funzionare. Ho un documento JSON che potrebbe essere simile:Gestione dell'eccezione "token non riconosciuto" in json personalizzato con Jackson
{
"test": {
"one":"oneThing",
"two": nonStandardThing(),
"three": true
}
}
voglio usare l'ObjectMapper per mappare ad un java.util.Map
e vorrei solo il nonStandardThing()
essere aggiunto come un valore stringa nella mia mappa per la chiave two
.
Quando ho eseguito questo attraverso il ObjectMapper.readValue(json, Map.class)
ottengo l'eccezione:
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'nonStandardThing': was expecting 'null', 'true', 'false' or NaN
at [Source: { "test":{"test1":nonStandardThing(),"test2":"two"}}; line: 1, column: 35]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1487)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277)
ho cercato di registrare un DeserializationProblemHandler
con la ObjectMapper
ma non è mai chiamato quando si verifica questo problema.
Ecco un'applicazione di esempio che mostra ciò che ho provato:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;
import java.io.IOException;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
public class JacksonDeserializerTest {
private Logger log = Logger.getLogger(JacksonDeserializerTest.class.getName());
public JacksonDeserializerTest() {
String validJson = "{ \"test\":{\"test1\":\"one\",\"test2\":\"two\"}}";
String invalidJson = "{ \"test\":{\"test1\":nonStandardThing(),\"test2\":\"two\"}}";
ObjectMapper mapper = new ObjectMapper();
mapper.addHandler(new DeserializationProblemHandler() {
@Override
public boolean handleUnknownProperty(DeserializationContext dc, JsonParser jp, JsonDeserializer<?> jd, Object bean, String property) throws IOException, JsonProcessingException {
System.out.println("Handling unknown property: " + property);
return false;
}
});
try {
log.log(Level.INFO, "Valid json looks like: {0}", mapper.readValue(validJson, Map.class).toString());
log.log(Level.INFO, "Invalid json looks like: {0}", mapper.readValue(invalidJson, Map.class).toString());
} catch (IOException ex) {
log.log(Level.SEVERE, "Error parsing json", ex);
}
}
public static void main(String[] args) {
JacksonDeserializerTest test = new JacksonDeserializerTest();
}
}
L'output è simile:
Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.jackson.JacksonDeserializerTest <init>
INFO: Valid json looks like: {test={test1=one, test2=two}}
Apr 24, 2015 1:40:27 PM net.acesinc.data.json.generator.jackson.JacksonDeserializerTest <init>
SEVERE: Error parsing json
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'nonStandardThing': was expecting 'null', 'true', 'false' or NaN
at [Source: { "test":{"test1":nonStandardThing(),"test2":"two"}}; line: 1, column: 35]
at com.fasterxml.jackson.core.JsonParser._constructError(JsonParser.java:1487)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError(ParserMinimalBase.java:518)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2300)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._reportInvalidToken(ReaderBasedJsonParser.java:2277)
at com.fasterxml.jackson.core.json.ReaderBasedJsonParser._matchToken(ReaderBasedJsonParser.java:2129)
Chiunque può segnalare il motivo per cui il gestore non viene mai chiamato? Oppure, se c'è una migliore analisi di questo documento json personalizzato (Jackson o no ...), fammi sapere.
E con "Deserializzatore di Jackson" si intende un diserializzatore personalizzato java.util.Map? Questo è quello che mi preoccupava ... –
Nemmeno quello fornirà una soluzione. Dalle discussioni nella mailing list 'Jackson', è chiaro che al momento esistono le funzionalità necessarie per le proprietà, non per i valori. Presumibilmente non hai alcun controllo sul processo di serializzazione? +1 per una domanda interessante comunque. :-) – PNS
Beh, in realtà potrei essere in grado di cambiare questo formato, ma è interessante che 'Jackson' non ti consenta di elaborare i valori. Bummer, perché potrebbe accadere di nuovo. Suppongo che potresti preprocessare il JSON per citare i valori non standard e renderlo valido. In ogni caso, la tua risposta (che in precedenza mi era passata per la testa) mi ha fatto riflettere di nuovo sul problema in modo diverso e ora sto rielaborando le cose per adattarle meglio. Grazie! –