简体   繁体   English

从JSON反序列化复杂的地图结构

[英]Deserializing complex map structure from JSON

I have a JSON structure like this: 我有一个像这样的JSON结构:

[
    {
        "topLevelOne": {
            "property1": false,

        },
        "topLevelTwo": [
            {
                "property2": false,
                "property3": false,
                "property4": false,
            },
            {
                "property2": false,
                "property3": false,
                "property4": false,
            }
        ]
    },

    {
        "topLevelOne": {
            "property1": false,

        },
        "topLevelTwo": [
            {
                "property2": false,
                "property3": false,

            },
            {
                "property2": false,
                "property3": false,
            },
        ]
    }
]

I am trying to convert this structure with Jackson into Map<CustomObject, List<CustomObject>> where topLevelOne corrsponds to Key , and the value is topLevelTwo ( List<CustomObject> ) 我试图将这个结构与Jackson转换为Map<CustomObject, List<CustomObject>> ,其中topLevelOneKey ,值为topLevelTwoList<CustomObject>

So I tried this: 所以我尝试了这个:

ObjectMapper JSONMapper = new ObjectMapper();
Map<CustomObject, List<CustomObject>> map = JSONMapper.readValue(json, new TypeReference<Map<CustomObject, List<CustomObject>>>(){});

However I'm getting this error message: com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class CustomObject ] 但是我收到此错误消息: com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class CustomObject ] com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class CustomObject

Could anyone point out what I'm doing wrong here? 谁能指出我在这里做错了什么? Maybe a code example how this can be achieved? 也许一个代码示例如何实现这一目标?

The json isn't valid because you have mixed types at the same level in your structure. json无效,因为您在结构中具有相同级别的混合类型。 I think you might accomplish what you want with a Map of Maps. 我想你可以通过地图地图完成你想要的任务。 I'm not sure about your custom Objects, so I'll use Strings in case it helps. 我不确定你的自定义对象,所以我会使用字符串以防万一。

If you define your json like this: 如果你像这样定义你的json:

[{
        "topLevelOne": [{
            "property1": false
        }],
        "topLevelTwo": [{
                "property2": false,
                "property3": false,
                "property4": false
            },
            {
                "property2": false,
                "property3": false,
                "property4": false
            }
        ]
    },

    {
        "topLevelOne": [{
            "property1": false

        }],
        "topLevelTwo": [{
                "property2": false,
                "property3": false

            },
            {
                "property2": false,
                "property3": false
            }
        ]
    }
]

you could read it with something like this: 你可以用这样的东西读它:

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

The built in Jackson Map deserialiser uses field names as keys and maps them to the related field values. 内置的Jackson Map反序列化器使用字段名称作为键并将它们映射到相关的字段值。

Your json is structured differently—it's a list of entries. 你的json结构不同 - 它是一个条目列表。 The simplest way to deserialise your map would be to read the list and build the map afterwards. 反序列化地图的最简单方法是读取列表并在之后构建地图。

You'll need a helper object to model the entries: 您需要一个辅助对象来为条目建模:

class CustomEntry {
    private CustomKey topLevelOne;
    private List<CustomObject> topLevelTwo;

    @JsonCreator
    public CustomEntry(@JsonProperty("topLevelOne") CustomKey topLevelOne, @JsonProperty("topLevelTwo") List<CustomObject> topLevelTwo) {
        this.topLevelOne = topLevelOne;
        this.topLevelTwo = topLevelTwo;
    }

    public CustomKey getTopLevelOne() {
        return topLevelOne;
    }

    public List<CustomObject> getTopLevelTwo() {
        return topLevelTwo;
    }
}

Then, 然后,

String json = ...
ObjectMapper mapper = new ObjectMapper();
// Read the list of map entries
List<CustomEntry> entries = mapper.readValue(json, new TypeReference<List<CustomEntry>>(){});
// Build the map
Map<CustomKey, List<CustomObject>> map = entries.stream().collect(Collectors.toMap(e -> e.topLevelOne, e -> e.topLevelTwo));

You could create a custom deserialiser to read the map directly from the list, but I'm not sure if it's worth the extra effort. 您可以创建一个自定义反序列化器直接从列表中读取地图,但我不确定是否值得付出额外的努力。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM