Преобразование файла. json в объект Java с помощью специального десериализатора Jackson - PullRequest
0 голосов
/ 02 августа 2020

В моем проекте у меня есть класс Closet, в котором хранится список одежды, называемой одеждой. Я реализовал код для сохранения информации об объектах Closet в файл. json, который выглядит следующим образом:

{
  "clothes" : [ {
    "name" : "mypants",
    "type" : "pants",
    "color" : "red",
    "size" : 32.0,
    "needsWashing" : false
  }, {
    "name" : "myshirt",
    "type" : "shirt",
    "color" : "blue",
    "size" : 2.0,
    "needsWashing" : false
  } ],
  "numberOfClothing" : 2
}

Однако, когда я пытаюсь получить файл Json, выдается исключение JsonProcessingException. и превратить его обратно в шкаф.

Closet closet = getDefaultObjectMapper().readValue(Paths.get("./data/Closet.json")
                .toFile(), Closet.class);

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

У меня такая же проблема с другим классом под названием StyleBoard, который представляет собой список Outfit (другой класс), а Outfit - это список одежды. Пример файла json для StyleBoard, записанного в. json. Файл:

содержит 2 костюма «рубашка и брюки» и «брюки и носки», каждый с 2 ​​объектами одежды

{
  "styleBoard" : [ {
    "clothes" : [ {
      "name" : "mypants",
      "type" : "pants",
      "color" : "blue",
      "size" : 32.0,
      "needsWashing" : false
    }, {
      "name" : "myshirt",
      "type" : "shirt",
      "color" : "blue",
      "size" : 0.0,
      "needsWashing" : false
    } ],
    "favorite" : false,
    "name" : "shirt and pants",
    "numberOfClothing" : 2
  }, {
    "clothes" : [ {
      "name" : "mypants",
      "type" : "pants",
      "color" : "blue",
      "size" : 32.0,
      "needsWashing" : false
    }, {
      "name" : "mysocks",
      "type" : "socks",
      "color" : "white",
      "size" : 3.0,
      "needsWashing" : false
    } ],
    "favorite" : false,
    "name" : "pants and socks",
    "numberOfClothing" : 2
  } ],
  "numberOfOutfits" : 2
}

Это сообщение об ошибке, которое я получаю:

Exception in thread "main" java.lang.RuntimeException: Cannot construct instance of `model.Clothing` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{
  "clothes" : [ {
    "name" : "myshirt",
    "type" : "shirt",
    "color" : "black",
    "size" : 2.09,
    "needsWashing" : false
  }, {
    "name" : "mypants",
    "type" : "pants",
    "color" : "red",
    "size" : 32.0,
    "needsWashing" : false
  } ],
  "collectionSize" : 2
}"; line: 3, column: 5] (through reference chain: model.Closet["clothes"]->java.util.ArrayList[0])
    at persistence.Json.fromJson(Json.java:43)
    at persistence.Json.parseUserCloset(Json.java:104)
    at ui.ClosetApp.loadUser(ClosetApp.java:195)
    at ui.ClosetApp.runClosetApp(ClosetApp.java:173)
    at ui.ClosetApp.doLogin(ClosetApp.java:103)
    at ui.ClosetApp.processLoginCommand(ClosetApp.java:68)
    at ui.ClosetApp.runLogin(ClosetApp.java:49)
    at ui.ClosetApp.<init>(ClosetApp.java:26)
    at ui.Main.main(Main.java:5)

Проблема, которую я заметил, которая может вызывать это, заключается в том, что когда я записываю свой объект Closet в файл. json, он добавляет дополнительное поле "numberOfClothing" , как вы можете видеть выше. Это не часть моего конструктора Closet, но у меня есть метод получения getNumberOfClothing. Когда я меняю имя этого получателя на getCollectionSize, это дополнительное поле, добавленное к моему json, становится "collectionSize" . Почему создается это дополнительное поле? Как я могу предотвратить это? Я думаю, что это дополнительное поле вызывает проблему с восстановлением объекта из json.

Ответы [ 2 ]

0 голосов
/ 02 августа 2020

Проблема в том, что мой класс Clothing не имеет конструктора с пустыми параметрами. Я просто добавил еще один конструктор.

Проблема с дополнительным нераспознанным полем «numberOfclothing» связана с тем, что у моих классов Closet и StyleBoard есть «геттеры» для значений, которые не были частью поля, но имели размер поля, использующие тип списка. Мне просто пришлось изменить имя этих методов, чтобы не включать "get" как часть их имени.

0 голосов
/ 02 августа 2020

Во-первых, вам нужно создать классы на основе вашего json. Вам необходимо создать класс Closet.

Fyi, я использую Lombok для краткости, т.е. убираю необходимость в методах getters, setters и toString. Если вы не используете Lombok, вы должны создать геттеры и сеттеры, поскольку библиотека Джексона будет использовать эти геттеры и сеттеры.

@Getter
@Setter
@ToString
@FieldDefaults(level= AccessLevel.PRIVATE)
public class Closet {
    // you need to create getter and setter method.
    // i use lombok so I don't need to create one
    List<Cloth> clothes = new ArrayList<>();
    Integer numberOfClothing;
}

Затем класс Cloth:

@Getter
@Setter
@ToString
@FieldDefaults(level= AccessLevel.PRIVATE)
public class Cloth {
    String name;
    String type;
    String color;
    Float size;
    Boolean needsWashing;
}

если вам нужно назвать член класса отличным от поля json, вы можете добавить аннотацию с помощью @JsonProperty («json имя поля»), например,

@JsonProperty("name")
String clothName;

Тогда фактический код преобразования:

Closet closet = JsonUtil.fromJson(jsonStr, Closet.class);

где класс JsonUtil содержит этот метод stati c (с использованием jackson):

public static <T> T fromJson(String jsonStr, Class<T> clazz){
    try {
        return new ObjectMapper().readValue(jsonStr, clazz);
    } catch (Exception e) {
        throw new RuntimeException(e.getMessage());
    }
}

Вы можете получить библиотеку jackson через зависимость maven ниже:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.0</version>
</dependency>

Для учебника Джексона вы можете погуглить. Ниже приведен лишь один из примеров: https://www.baeldung.com/jackson-object-mapper-tutorial

И я оставляю вам Таблицу стилей, поскольку шаги в точности такие же, как и в классе Closet.

...