Ich habe eine Klasse, die wie folgtSerialize/Deserialize Map <String, Object> mit Jackson
public class MyClass {
private String val1;
private String val2;
private Map<String,Object> context;
// Appropriate accessors removed for brevity.
...
}
von Objekt zu JSON Ich bin auf der Suche in der Lage sein, um die Hin- und Rückfahrt mit Jackson sieht und zurück . Ich kann das Objekt über feine serialisiert und erhalten die folgende Ausgabe:
{
"val1": "foo",
"val2": "bar",
"context": {
"key1": "enumValue1",
"key2": "stringValue1",
"key3": 3.0
}
}
Das Problem, das ich in laufende bin ist, dass, da die Werte in der serialisierten Karte keine Typinformationen haben, sind sie nicht korrekt deserialisiert. Im obigen Beispiel sollte enumValue1 beispielsweise als Enumerationswert deserialisiert werden, wird aber stattdessen als String deserialisiert. Ich habe Beispiele dafür gesehen, welchen Typ ich auf verschiedene Dinge anwende, aber in meinem Szenario werde ich nicht wissen, was die Typen sind (sie werden vom Benutzer generierte Objekte sein, die ich vorher nicht kennen werde), also muss ich es sein kann die Typinformation mit dem Schlüsselwertpaar serialisieren. Wie kann ich das mit Jackson erreichen?
Für die Aufzeichnung verwende ich Jackson Version 2.4.2. Der Code, den ich die Rundfahrt zu testen, bin mit ist wie folgt:
@Test
@SuppressWarnings("unchecked")
public void testJsonSerialization() throws Exception {
// Get test object to serialize
T serializationValue = getSerializationValue();
// Serialize test object
String json = mapper.writeValueAsString(serializationValue);
// Test that object was serialized as expected
assertJson(json);
// Deserialize to complete round trip
T roundTrip = (T) mapper.readValue(json, serializationValue.getClass());
// Validate that the deserialized object matches the original one
assertObject(roundTrip);
}
Da dies ein Frühling basiertes Projekt wird der Mapper wie folgt erstellt werden:
@Configuration
public static class SerializationConfiguration {
@Bean
public ObjectMapper mapper() {
Map<Class<?>, Class<?>> mixins = new HashMap<Class<?>, Class<?>>();
// Add unrelated MixIns
..
return new Jackson2ObjectMapperBuilder()
.featuresToDisable(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS)
.dateFormat(new ISO8601DateFormatWithMilliSeconds())
.mixIns(mixins)
.build();
}
}
Nun, natürlich wird ein 'Objekt' keine Typinformation haben; Es gibt keinen anderen Weg als 1. Erstellen Sie ein POJO für Ihre 'context' Instanzvariable (bevorzugt); oder 2. verwende keine 'Map', sondern einen 'ObjectNode'. In jedem Fall ist dies ein primäres Beispiel für einen Code-Geruch. –
fge
Die Variable 'context' wird ähnlich wie' HttpSession' verwendet (sie repräsentiert Spring Batch's 'ExecutionContext', um genau zu sein), also würde ich es nicht für einen Geruch halten ... dafür ist eine 'Map' gedacht. Was ich nicht verstehe ist, warum Jackson kein Feld hinzufügen kann, das den Typ angibt. Wenn es den Wert hat, hat es die Klasse und kann daher den Typ bestimmen. Was vermisse ich? –
Und wo würde es dieses Feld hinzufügen? Sie sagen ihm nur, das zu einem 'Objekt' zu deserialisieren. Der Vorteil mit einem 'ObjectNode' ist zumindest, dass Sie JSON direkt erhalten; Sie können also den Typ des Feldes mit allem abfragen, was 'JsonNode' helfen soll. – fge