java - JSON - 嵌套 map 的自定义键序列化

标签 java json serialization jackson

我有一个嵌套的 Map<StructureNode, Map<String, String>>为此,我需要一个自定义 key 序列化器和反序列化器(StructureNode 包含对其他对象的引用,这些对象需要用作此 map 的 key )。我为此使用了以下方法:

Jackson Modules for Map Serialization

给出以下结果。自定义序列化程序:

public class StructureNodeKeySerializer extends JsonSerializer<StructureNode> {

    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public void serialize(StructureNode value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        StringWriter writer = new StringWriter();
        mapper.writeValue(writer, value.copyUpwards());
        gen.writeFieldName(writer.toString());
    }
}

自定义反序列化器:

public class StructureNodeKeyDeserializer extends KeyDeserializer  {

    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public Object deserializeKey(String key, DeserializationContext ctxt) throws IOException {
        return mapper.readValue(key, StructureNode.class);
    }
}

用法:

@JsonDeserialize(keyUsing = StructureNodeKeyDeserializer.class) @JsonSerialize(keyUsing = StructureNodeKeySerializer.class)
private Map<StructureNode, String> structureIds;
@JsonDeserialize(keyUsing = StructureNodeKeyDeserializer.class) @JsonSerialize(keyUsing = StructureNodeKeySerializer.class)
private Map<StructureNode, Map<String, String>> metadata;

这正确地序列化了一个 Map<StructureNode, String> , 但应用于嵌套 Map<StructureNode, Map<String, String>> ,它给出了以下错误:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: java.lang.String cannot be cast to structure.StructureNode

Jackson 似乎对“子 map ”使用了相同的自定义序列化方法。有没有解决这个问题的好方法,而不用用另一个自定义(非 Map)对象替换“子 map ”?

最佳答案

你可以用

来解决这个问题
public static class Bean{
    @JsonSerialize(using = MapStructureNodeKeySerializer.class)
    public Map<StructureNode, Map<String, String>> metadata;
}

并以稍微不同的方式实现您的序列化器:

public static class MapStructureNodeKeySerializer 
        extends JsonSerializer<Map<StructureNode, Object>> {

    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public void serialize(Map<StructureNode, Object> value, JsonGenerator gen, 
                          SerializerProvider serializers) throws IOException {
        gen.writeStartObject();

        for(Map.Entry<StructureNode, Object> val: value.entrySet()){
            // your custom serialization code here
            StringWriter writer = new StringWriter();
            mapper.writeValue(writer, val.getKey().copyUpwards());

            gen.writeObjectField(writer.toString(), val.getValue());
        }

        gen.writeEndObject();
    }
}

或者如果你想保留 keyUsing = StructureNodeKeySerializer.class

public static class Bean{
    @JsonSerialize(keyUsing = StructureNodeKeySerializer.class)
    public Map<StructureNode, Map<String, String>> metadata;
}

你可以这样实现它:

public static class StructureNodeKeySerializer extends JsonSerializer {

    private static final ObjectMapper mapper = new ObjectMapper();

    @Override
    public void serialize(Object value, JsonGenerator gen,
                          SerializerProvider serializers) throws IOException {

        if (value instanceof StructureNode){ // <= type of 1-st level Map key
            // your custom serialization code here
            StringWriter writer = new StringWriter();
            mapper.writeValue(writer, ((StructureNode)value).copyUpwards());
            gen.writeFieldName(writer.toString());
        }else if(value instanceof String){   // <= type of 2-nd level Map key
            gen.writeFieldName((String) value);
        }
    }
}

关于java - JSON - 嵌套 map 的自定义键序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46836372/

相关文章:

javascript - Webpack:自定义加载器 - 重用文件扩展名

javascript - 如何在D3.js中绘制JSON列表?

scala - SparkContext 在伴随对象内不可序列化

c# - 使用 UTF-8 编码反序列化 XML

c++ - 处理可能的空指针的类的 boost 序列化

Java:计算内存使用量时结果不准确

java - 将 @JsonCreator 与嵌套 Json 对象一起使用时面临问题

java - pageradapter 中的 getResources 数组 xml

c# - Rfc2898DeriveBytes for .NET 和 Java 生成不同的值

c# - Qtip数据未定义错误