[英]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.