簡體   English   中英

使用自定義解串器 Z7930C951E609E461E8Z226 將 a.json 文件轉換為 Java object

[英]Converting a .json file into a Java object with a custom deserializer Jackson

在我的項目中,我有一個名為 Closet 的 class ,其中包含一個名為衣服的服裝清單。 我已經實現了將 Closet 對象的信息保存到 a.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 程序員,我不確定如何解決這個問題。 我已經通過創建自定義反序列化器進行了一些搜索,但是,我不確定如何使用我的嵌套對象(Clothing 嵌套在 Closet 中)實現反序列化器,以及 Closet object 中可能有任意數量的 Clothing 的事實。

我對另一個名為 StyleBoard 的 class 有同樣的問題,它是 Outfit (另一個類)的列表,而 Outfit 是 Clothing 的列表。 寫入.json 文件的 StyleBoard 的 jsonfile 示例是

包含 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 Object 寫入 a.json 文件時,它添加了一個額外的字段“numberOfClothing” ,如上所示。 這不是我的 Closet 構造函數的一部分,但是我確實有一個名為 getNumberOfClothing 的 getter。 當我將此 getter 的名稱更改為 getCollectionSize 時,添加到我的 json 的這個額外字段變為"collectionSize" 為什么要創建這個額外的字段? 我該如何預防? 我認為這個額外的字段導致從 json 重建 object 的問題。

首先,您需要根據您的 json 創建類。 您需要創建一個壁櫥 class。

僅供參考,我使用 Lombok 是為了簡潔,即不需要 getter、setter 和 toString 方法。 如果您不使用 Lombok,則必須創建 getter 和 setter,因為 Jackson 庫將使用這些 getter 和 setter。

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

然后是一塊布 class:

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

如果您需要將 class 成員命名為不同於 json 字段,您可以使用 @JsonProperty("json field name") 進行注釋,例如

@JsonProperty("name")
String clothName;

然后是實際的轉換代碼:

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

其中 JsonUtil class 包含此 static 方法(使用傑克遜):

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

您可以通過下面的 maven 依賴項獲取 jackson 庫:

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

jackson教程,可以google一下。 以下只是示例之一: https://www.baeldung.com/jackson-object-mapper-tutorial

我把樣式板留給你,因為步驟與壁櫥 class 完全相同。

問題在於我的 Clothing class 沒有帶有空參數的構造函數。 我只是添加了另一個構造函數。

附加無法識別的字段“numberOfclothing”的問題是由於我的 Closet 和 StyleBoard 類都有“getter”,用於不屬於字段的值,但用於使用 List 類型的字段大小。 我只需要更改這些方法的名稱,使其名稱中不包含“get”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM