当前位置: 首页 > 知识库问答 >
问题:

用于映射序列化的杰克逊模块

梁修贤
2023-03-14

我有一个包含地图(非字符串键)和其他一些字段的类。

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模块。

我关注了这篇文章,并扩展了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()输出中序列化/反序列化整个map结构。所以尝试了不同的注释:

@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() 方法)。有没有更好的方法?

共有1个答案

陈康胜
2023-03-14

最终使用此序列化程序:

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;

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

 类似资料:
  • 有没有办法让Jackson序列化某个流对象(并在之后关闭)?这样地: 使现代化 澄清:我想流式传输内容,而不仅仅是将其序列化到单个String对象。

  • 问题内容: 我正在使用Jackson XML映射器将XML反序列化为POJO。XML看起来像 我的课看起来像 我想将电话号码设置为“电话”类别中的号码。我无法更改XML或类的构造方式。我收到无法构造错误的实例,并创建了一个AgencyPhone构造函数 但这没有用。那么如何反序列化嵌套实例。 问题答案: 您可以编写自己的自定义解串器来实现此目的。这是使您入门的代码:

  • 问题内容: 我有一个JSON字符串,将标记为而不是。因此,例如,如果我有一个没有子对象的对象,我将收到类似以下的字符串: 我想将其反序列化为Parent类,并将子级正确设置为一个空的子级列表。 对于上述JSON字符串,我想要一个对象,其设置为,而设置为。 我会知道如何在整个课堂上使用注释 然后 但是,我想解决一个从字符串正确实例化List的一般问题: 我能得到类似的东西吗? 问题答案: 几个选择;

  • 问题内容: 我有以下课程- 我正在使用objectMapper.valueToTree(sections)将其转换为JsonNode。但是,当我打印相同的内容时,我仅从Entity类中看到id和name字段,而从Images列表中看不到任何内容。我是否需要添加任何种类的特殊逻辑或注释以确保同时打印列表。 以下是主要课程- 问题答案: 您需要为Entity#images添加getter和setter

  • 我明白它无法从嵌套JSON反序列化字符串。我解决这个问题的一个方法是通过编写自定义映射器 但是只要pojo中有变化,这就需要修改映射器,添加/删除字段。Mixin工作时没有任何变化,我该如何更新我的Mixin来处理objectId呢?

  • 我想用scala中的jackson反序列化json json_结构: {“type”:“struct”,“fields”:[{“name”:“code_role”,“type”:“string”,“nullable”:true,“metadata”:{“HIVE_type_string”:“string”},{“name”:“libelle_role”,“type”:“string”,“nulla