Как я могу создать несколько типов объектов Java, используя один файл JSON с помощью Jackson Mapper? - PullRequest
0 голосов
/ 03 июня 2018

Я хочу создать несколько типов Java-объектов, используя один JSON-файл.

Я думал о хранении различных типов Java-объектов в форме карты, где ключом будет имя типа объекта, а значение будетбыть самим объектом, как показано ниже

Field2_AllIn1.json

 {
 "fetchMapOfStringType": {

        "hi": "hello"

    },

    "fetchMapFieldType": {

        "5b0b8a5545424a20487ee2bc": {
            "fieldId": "5b0b8a5545424a20487ee2bc",

            "value": "25",
            "values": [],
            "visible": true,
            "fieldValidationErrors": [],
            "globalValidationErrors": [

                {
                    "fieldValidationId": "5b0b8a5545424a20487ee2bc",
                    "validationErrorMessage": "this is error"

                }
            ],
            "formulaErrors": []
        }

    }


 }

первый хранит простой тип String, второй хранит объект Java типа map, где Field - это пользовательский класс

public class JsonJacksonAllInOne {

    public static void main(String args[]) throws JsonParseException, JsonMappingException, IOException{



        try {



            // read JSON from a file
            Map<String, Object> map = mapper.readValue(
                    new File("C://json/Field2_AllIn1.json"), 
                    new TypeReference<Map<String, Object>>() {
            });

            //type String
            //String type works fine
            Object obj1 = map.get("fetchMapOfStringType");
             Map<String, String> mapStringType  =  (Map<String, String>) obj1;
            System.out.println(mapStringType.get("hi"));//this prints hello


             //second type ... type casting to object type to objectId and Field map 
             Map<ObjectId, Field> map1 = (Map<ObjectId, Field>) map.get("fetchMapFieldType");

             ObjectId k1 = new ObjectId("5b0b8a5545424a20487ee2bc");
             Field f1 = map1.get(k1);
             //this code gives value of f1 as null


             // this gives class cast exception 
             // java.util.LinkedHashMap cannot be cast to com.dto.Field

                Field f2 =  map1.get("5b0b8a5545424a20487ee2bc");


        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }



    }
}

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

1 Ответ

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

Проблема с этой строкой:

// read JSON from a file
Map<String, Object> map = mapper.readValue(
                    new File("C://json/Field2_AllIn1.json"), 
                    new TypeReference<Map<String, Object>>() {
            });

Когда вы читаете json как карту, он будет анализировать весь json как LinkedHashMap (для сохранения порядка, в противном случае также может использоваться HashMap).После этого вы не можете привести его к другому POJO / Beans.

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

public static void main(String[] args) {

    try {

        ObjectMapper mapper = new ObjectMapper();

        // read JSON from a file as a tree
        JsonNode map = mapper.readTree(new File("/home/pratapi.patel/config.json"));

        // fetch json node from the tree
        JsonNode obj1 = map.get("fetchMapOfStringType");

        // convert obj1 (JsonNode) as Map<String, String>
        Map<String, String> mapStringType =
                mapper.readValue(mapper.treeAsTokens(obj1), new TypeReference<Map<String, String>>() {
                });

        // prints hello
        System.out.println(mapStringType.get("hi"));

        // fetch another json node from the tree
        JsonNode map1 =  map.get("fetchMapFieldType");

        // convert map1 (JsonNode) as Map<ObjectId, Field>
        Map<ObjectId, Field> mapFieldType = mapper.readValue(mapper.treeAsTokens(map1), new TypeReference<Map<ObjectId, Field>>() {
        });

        ObjectId k1 = new ObjectId("5b0b8a5545424a20487ee2bc");
        Field f1 = mapFieldType.get(k1);

        System.out.println(f1);

    } catch (IOException e) {
        e.printStackTrace();
    }
}

Кроме того, поскольку ObjectId используется в качестве ключа в Map, он должен быть окончательным, и для правильной работы его следует переопределить equals / hashCode.

public class ObjectId {

    private final String value;

    @JsonCreator
    public ObjectId(@JsonProperty("value") String value) {
        super();
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    /**
     * Auto generated in eclipse
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((value == null) ? 0 : value.hashCode());
        return result;
    }

    /**
     * Auto generated in eclipse
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        ObjectId other = (ObjectId) obj;
        if (value == null) {
            if (other.value != null)
                return false;
        } else if (!value.equals(other.value))
            return false;
        return true;
    }
}
...