Десериализация сложной структуры карты из JSON - PullRequest
0 голосов
/ 28 июня 2018

У меня есть такая структура 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,
            },
        ]
    }
]

Я пытаюсь преобразовать эту структуру с Джексоном в Map<CustomObject, List<CustomObject>>, где topLevelOne соответствует Key, а значение равно topLevelTwo (List<CustomObject>)

Итак, я попробовал это:

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

Однако я получаю это сообщение об ошибке: com.fasterxml.jackson.databind.JsonMappingException: Can not find a (Map) Key deserializer for type [simple type, class CustomObject]

Может ли кто-нибудь указать, что я здесь делаю неправильно? Может быть, пример кода, как это может быть достигнуто?

Ответы [ 2 ]

0 голосов
/ 29 июня 2018

Встроенный десериализатор Джексона Map использует имена полей в качестве ключей и сопоставляет их с соответствующими значениями полей.

Ваш json структурирован по-другому - это список записей. Самый простой способ десериализации вашей карты - прочитать список и построить карту впоследствии.

Вам понадобится вспомогательный объект для моделирования записей:

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

Тогда

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

Вы можете создать собственный десериализатор для чтения карты непосредственно из списка, но я не уверен, стоит ли это дополнительных усилий.

0 голосов
/ 28 июня 2018

JSON недопустим, поскольку в вашей структуре смешанные типы на одном уровне. Я думаю, что вы могли бы достичь того, что вы хотите с помощью карты карт. Я не уверен насчет ваших пользовательских объектов, поэтому я буду использовать строки в случае, если это поможет.

Если вы определите свой 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
            }
        ]
    }
]

Вы можете прочитать это примерно так:

Map<String, Map<String,String>> map = mapper.readValue(json, new TypeReference <Map<String, Map<String,String>>>(){});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...