【问题标题】:Java : Json with duplicate keys to map using JacksonJava:具有重复键的 Json 使用 Jackson 进行映射
【发布时间】:2014-12-30 18:19:24
【问题描述】:

我有一个具有相同键但不同值的 json 文件,如下所示,

{
    "domains" : {
        "A" : {
            "name" : "a",
            "type" : "a1"
        },
        "B"  :{
            "name" : "r",
            "type" : "g1"
         },
        "A" : {
           "name" : "b",
           "type" : "b1"
        }
    }
}

来自外部系统。 如何将json转成java map对象并访问key的不同值:A

我正在使用类似下面的东西,

map = mapper.readValue(json, new TypeReference<HashMap<String,String>>(){});

它返回一个带有唯一键的映射。但我需要一个地图对象来保存 json 文件中的所有数据。

无论如何要做到这一点?

【问题讨论】:

  • 解析此类 JSON 的结果是未定义的“按定义”;使用 Jackson 能够做到这一点的唯一方法是自己解析它(实例化 JsonParser; 并逐个读取令牌)。但是,首先,您应该用大锤敲击该 JSON 的生产者,并告诉他/她去阅读 RFC 7159。
  • 顺便说一句,相关文字:RFC 7159, section 4:“当对象中的名称不唯一时,接收到此类对象的软件的行为是不可预测的。”

标签: java json hashmap jackson


【解决方案1】:

我同意 @fge 的 cmets。

但如果你真的坚持要解决这个问题,你可以继承HashMap(或任何其他Map),覆盖它的put 方法,并使用你想要的任何机制处理重复项。只需确保您的 Map 具有无参数构造函数即可。

Guava 也可能具有允许保留重复项的数据类型 (Multimap?)。如果是这样,您将需要使用 Jackson 的 Guava 模块:https://github.com/FasterXML/jackson-datatype-guava

【讨论】:

  • 实际上,使用 Guava 有一个更简单的方法:使用 ForwardingMap。当然,这并不能阻止 JSON 一开始就被破坏的事实。
【解决方案2】:

因为related question 被标记为重复而回答,但似乎解决了需要创建具有重复键的 JSON 的相反问题。这就是 Java 模型 -> 带有重复键的 JSON。

我发现最简单的方法是实现custom serializer

public class CustomSerializer extends StdSerializer<ModelToSerialize> {


    public CustomSerializer(Class<ModelToSerialize> t) {
        super(t);
    }

    @Override
    public void serialize(ModelToSerialize value, com.fasterxml.jackson.core.JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("DuplicateJsonKey", value.getDup1());
        gen.writeStringField("DuplicateJsonKey", value.getDup2());
        // Map all other values on value that you want to be present in the JSON
        gen.writeEndObject();
    }
}

然后当你去序列化时:

SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(ModelToSerialize.class, new CustomSerializer(ModelToSerialize.class));
objectMapper.registerModule(simpleModule);
String sr = objectMapper.writeValueAsString(modelToSerialize);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多