Как использовать противоречивую структуру json для одного и того же ключа, используя jackson (com.fasterxml.jackson)? - PullRequest
1 голос
/ 13 мая 2019

В приведенной ниже структуре JSON параметр fileMetaData имеет разные типы.Jackson выдает исключение com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of com.XXX.XXX.XXX.FILENAME out of START_ARRAY token.

Пример JSON Полезная нагрузка:

[
    {
        "fileName": "file_name_1",
        "fileMetaData": {
          "abcd": "valueabcd",
          "xyz": "valuexyz"
        }
    },
    {
        "fileName": "file_name_2",
        "fileMetaData": [
            {
                "123": "value123",
                "456": "value456"
            },
            {
                "123": "value123-1",
                "456": "value456-1"
            }
        ]
    },
    {
        "fileName": "file_name_3",
        "fileMetaData": {
            "key1": {
                "key11": "val11",
                "key12": "val22"
            },
            "key2": "val2"
        }
    },
    {
        "fileName": "abc.xyz",
        "fileMetaData": null
    }
]

Как его десериализовать?

Ответы [ 2 ]

2 голосов
/ 13 мая 2019

Обычно Jackson преобразует JSON Array в List и JSON Object в Map.В этом случае мы можем использовать общий тип Object, и он будет правильно установлен.Нам просто нужно проверить, какой тип у нас есть в данном случае, и правильно привести тип Java.См. Пример ниже:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.util.List;
import java.util.Map;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper();
        TypeReference<List<Item>> typeReference = new TypeReference<List<Item>>() {
        };
        List<Item> items = mapper.readValue(jsonFile, typeReference);

        items.forEach(item -> {
            if (item.isArray()) {
                System.out.println("List => " + item.getFileMetaDataAsList());
            } else if (item.isObject()) {
                System.out.println("Map => " + item.getFileMetaDataAsMap());
            }
        });

    }
}

class Item {

    private String fileName;
    private Object fileMetaData;

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public Object getFileMetaData() {
        return fileMetaData;
    }

    public void setFileMetaData(Object fileMetaData) {
        this.fileMetaData = fileMetaData;
    }

    public boolean isObject() {
        return this.fileMetaData instanceof Map;
    }

    public boolean isArray() {
        return this.fileMetaData instanceof List;
    }

    public Map<String, Object> getFileMetaDataAsMap() {
        return (Map<String, Object>) this.fileMetaData;
    }

    public List<Map<String, Object>> getFileMetaDataAsList() {
        return (List<Map<String, Object>>) this.fileMetaData;
    }

    @Override
    public String toString() {
        return "Item{" +
                "fileName='" + fileName + '\'' +
                ", fileMetaData=" + fileMetaData +
                '}';
    }
}

, который для вашей JSON распечатки полезной нагрузки:

Map => {abcd=valueabcd, xyz=valuexyz}
List => [{123=value123, 456=value456}, {123=value123-1, 456=value456-1}]
Map => {key1={key11=val11, key12=val22}, key2=val2}
0 голосов
/ 14 мая 2019

Вы можете десериализовать данные в JSONNode . Вы можете использовать метод isArray (), чтобы проверить и затем преобразовать его в POJO соответственно.

  1. Считать данные JSON как JsonNode
        String json = "{ \"f1\" : \"v1\" } ";

        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode = mapper.readTree(json);
  1. Проверьте JSONNode, который использует isArray ()
        if(jsonNode .isArray()){
            //Do below
        }
  1. Преобразование узла в POJO
        // acquire reader for the right type
        ObjectReader reader = mapper.readerFor(new TypeReference<List<String>>() {
        });
        // use it
        List<String> list = reader.readValue(arrayNode);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...