【问题标题】:Jackson Modules for Map Serialization用于地图序列化的杰克逊模块
【发布时间】:2014-10-05 23:30:27
【问题描述】:

我有一个类,其中包含一个 Map(带有非 String 键)和一些其他字段。

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
}

我想使用 Jackson 序列化和反序列化这个类。 我看到了一种不同的方法,并决定尝试使用jackson modules

我关注this post 并扩展了 JsonDeserializer 和 JsonSerializer。问题是这些类应该是类型的,所以它应该看起来像

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

KeySerializer 也是如此。

然后添加到模块中:

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

但这显然是错误的,因为我遇到了异常:

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'

我可以将我的序列化器和反序列化器输入到 MyClass,但是我不得不手动解析所有这些,这是不合理的。

更新:

我设法通过使用注释绕过了代码中的模块创建

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

但是我必须自己从 toString() 输出序列化/反序列化整个地图结构。所以尝试了不同的注释:

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

MyKeyDeserializer 扩展 org.codehaus.jackson.map.KeyDeserializer 并覆盖该方法的地方

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

然后手动反序列化我的密钥,但再次从我的密钥类的 toString() 输出。

这不是最优的(这依赖于 toString() 方法)。有没有更好的办法?

【问题讨论】:

标签: java serialization map jackson jackson-modules


【解决方案1】:

最终使用了这个序列化器:

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());
    }
}

还有这个反序列化器:

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);
    }
}

注释了我的地图:

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

这是对我有用的解决方案,希望这对其他人有帮助。

【讨论】:

  • 看起来很有帮助,但您可能想解释一下 AlgFilterKey 是什么,或者删除它并在其位置放置一些通用的东西。
  • 谢谢,这很有帮助
猜你喜欢
  • 2012-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-04
  • 2014-02-21
相关资源
最近更新 更多