繁体   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