Jackson Modules for Card Serialization

I have a class that contains a map (with a non String key) and some other fields.

public class MyClass() { private Map<KeyObject, OtherObject> map; private String someField; public MyClass(Map<KeyObject, OtherObject> map, String someField) { this.map = map; this.someField = someField; } // Getters & Setters } 

I would like to serialize and deserialize this class using Jackson. I saw different ways to do this and decided to try using jackson modules .

I followed this post and expanded on JsonDeserializer and JsonSerializer. The problem is that these classes must be printed, so it should look like

 public class keyDeserializer extends JsonDeserializer<Map<KeyObject, OtherObject>> { ... } 

The same goes for KeySerializer.

Then adding to the module:

 module.addSerializer(new keySerializer()); module.addDeserializer(Map.class, new keyDeserializer()); 

But this is wrong because I get an exception:

 keySerializer does not define valid handledType() -- must either register with method that takes type argument or make serializer extend 'org.codehaus.jackson.map.ser.std.SerializerBase' 

I could use my serializer and deserializer for MyClass , but then I had to manually parse all this, which is not reasonable.

UPDATE:

I managed to get around creating a module in code using annotations

 @JsonDeserialize(using = keyDeserializer.class) @JsonSerialize(using = keySerializer.class) private Map<KeyObject, OtherObject> map; 

But then I have to serialize / deserialize the entire map structure myself from the output of toString (). Therefore, I tried another annotation:

 @JsonDeserialize(keyUsing = MyKeyDeserializer.class) private Map<KeyObject, OtherObject> map; 

Where MyKeyDeserializer extends org.codehaus.jackson.map.KeyDeserializer and overrides the method

 public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException {...} 

Then manually deserialize my key, but again from the output of toString () of my key class.

This is not optimal (this depends on the toString () method). Is there a better way?

+5
source share
1 answer

Finished using this serializer:

 public class MapKeySerializer extends SerializerBase<Object> { private static final SerializerBase<Object> DEFAULT = new StdKeySerializer(); private static final ObjectMapper mapper = new ObjectMapper(); protected MapKeySerializer() { super(Object.class); } @Override public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { return DEFAULT.getSchema(provider, typeHint); } @Override public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException { if (null == value) { throw new JsonGenerationException("Could not serialize object to json, input object to serialize is null"); } StringWriter writer = new StringWriter(); mapper.writeValue(writer, value); jgen.writeFieldName(writer.toString()); } } 

And this deserializer:

 public class MapKeyDeserializer extends KeyDeserializer { private static final ObjectMapper mapper = new ObjectMapper(); @Override public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException { return mapper.readValue(key, MyObject.class); } } 

My annotated map:

 @JsonDeserialize(keyUsing = MapKeyDeserializer.class) @JsonSerialize(keyUsing = MapKeySerializer.class) private Map<KeyObject, OtherObject> map; 

This is a solution that worked for me, hope it helps others.

+9
source

Source: https://habr.com/ru/post/1200147/


All Articles