Non proprio sicuro del modo migliore per spiegare il problema, così ho montato lo stesso codice sia di java che di kotlin per una migliore dimostrazione.In Kotlin, Jackson Errore di deserializzazione con classe dati
Quando leggo JSON, sembra che imponga che un valore di bean di dati sia NULL anche se il parametro non è nemmeno parte del json per iniziare e il bean di dati imposta il valore predefinito del campo mancante. In java funziona correttamente senza mai tentare di annullare il valore che non è mai stato fornito per iniziare. In Kotlin sembra che si rompa perché cerca di annullare un campo non annullabile.
In Kotlin
data class Pojo(val name: String, val age: Int, val list: List<String> = emptyList(), val ts: Date = Date())
private val mapper: ObjectMapper = ObjectMapper().registerModule(KotlinModule())
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
fun main(args: Array<String>) {
mapper.readValue("""{"name": "John Doe", "list": ["yellow", "green"], "age": 42}""", Pojo::class.java)
}
Che genera un'eccezione di
java.lang.IllegalArgumentException: Parameter specified as non-null is null: method Pojo.<init>, parameter ts
In Java (tutto funziona bene)
public class Transform {
private static ObjectMapper mapper = new ObjectMapper()
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
public static class Pojo {
private String name;
private int age;
private List<String> list;
private Date ts = new Date();
<getters and setters for all>
}
public static void main(String[] args) throws IOException {
String json = "{\"name\": \"John Doe\", \"list\": [\"yellow\", \"green\"], \"age\": 42}";
Pojo p = mapper.readValue(json, Pojo.class);
System.out.printf("Bean: name=%s, age=%s, list=%s, ts=%s\n", p.name, p.age, p.list, p.ts);
}
}
Anche se faccio una classe invece di un dato classe in kotlin, ha ancora errori allo stesso modo.
La mia domanda è, come posso ottenere la deserializzazione di Jackson per lavorare a Kotlin con i miei POJO. Il comportamento previsto è che "dovrebbe" interrompersi se viene passato un valore nullo/errato per qualcosa in cui null non è consentito. Ma nello scenario sopra in cui non è stato fatto alcun tentativo di cambiare il campo ts in null, avrebbe dovuto usare il valore di default come fa con java.
L'unica cosa che attraversa la mia mente che sembra funzionare è di non usare il concetto di bean di dati a tutti e di scrivere i miei fagioli come
class Pojo(val name: String, val age: Int) {
var list: List<String> = emptyList()
var ts: Date = Date()
}
Ma poi i miei .equals non funziona ed è consente agli altri a valle di manipolare il contenuto dell'elenco e le proprietà di ts quando voglio che siano di sola lettura.
Corretto, questa modifica era nuova per 2.8.x e * non può * essere ripristinata su versioni precedenti, quindi è necessario eseguire l'aggiornamento poiché le nuove API sono state aggiunte a Jackson in modo esplicito per dare maggiore controllo ai moduli del plugin. –
Grazie, ha funzionato. Stavo usando 2.7.5 che era l'ultima volta al momento in cui ho iniziato questo piccolo sforzo. Non ho mai pensato che avrei semplicemente dovuto aggiornare le librerie. Felice di una soluzione facile. – Ryba