Java: 使用Jackson将具有重复键的Json转换为Map

4

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

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

这段文本来自于外部系统。 如何将json转换为java map对象并访问键A的不同值。

我使用类似以下的方法:

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

使用返回唯一键的map函数无法满足我的需求。我需要一个能够容纳从JSON文件中获取到的所有数据的map对象。

有什么方法可以实现这个需求吗?


11
解析这种JSON的结果在定义上是未知的;你唯一能够使用Jackson实现的方法就是自己进行解析(实例化一个JsonParser,并逐个读取标记)。不过首先你应该用大锤打那个JSON的生产者,并告诉他/她去阅读RFC 7159。 - fge
4
顺便提一下,相关文本:RFC 7159,第4节:“当对象内的名称不唯一时,接收此类对象的软件的行为是不可预测的。” - fge
2个回答

2

我同意@fge的评论。

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

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


3
实际上,使用Guava有更简单的方法:使用“ForwardingMap”。当然,这并不能防止JSON一开始就有问题。 - fge

1

由于一个相关问题被标记为重复,但似乎解决的是相反的问题,即需要创建具有重复键的JSON。因此,这是Java模型 -> 具有重复键的JSON。

我发现最简单的方法是实现一个自定义序列化器

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接