繁体   English   中英

为什么 spring 引导可以在没有默认构造函数的情况下反序列化 class?

[英]Why spring boot can deserialize class without default constructor?

I wonder why spring boot can deserialize the class which has no default constructor by Jackson's objectMapper,but when i mannually using objectMapper in unit test,it can not deserialize(com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of xxx (不存在像默认构造函数一样的创建者):无法从 Object 值反序列化(没有基于委托或属性的创建者)。

这是我的 controller:

  @PostMapping("/precise")
  public Resp<List<MatchedOutLineResponseDTO>> getPreciseMatchedOutLine(
  @RequestBody List<MatchedOutLineRequestDTO> request) 

这是我的pojo:

@Getter
public class MatchedOutLineRequestDTO {

   private String uuid;
   private JSONObject outLineGeometry;

   public MatchedOutLineRequestDTO(String uuid, JSONObject outLineGeometry) {
     this.uuid = uuid;
     this.outLineGeometry = outLineGeometry;
   }
 }

有人可以告诉我原因吗?

  1. Json 序列化(对象转 JSON)
    • 不需要无参数构造函数
    • 只需要要公开的属性的访问器方法 ( get... )
  2. Json 反序列化(JSON转对象)
    • 需要无参数构造函数和设置器,因为 object 映射器首先使用无参数构造器创建 class,然后使用设置器设置字段值。

考虑下面的代码示例

public class Test {
    @Getter
    static class Dummy {
        private String uuid;
        private Date date;
        private JSONObject jsonObject;

        public Dummy(String uuid, Date date, JSONObject jsonObject) {
            this.uuid = uuid;
            this.date = date;
            this.jsonObject = jsonObject;
        }
    }

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("Name", "John Doe");
        jsonObject.put("Age", "Unknown");
        Dummy dummyObj = new Dummy(UUID.randomUUID().toString(), new Date(), jsonObject);

        String jsonStr = mapper.writeValueAsString(dummyObj);
        System.out.println("Serialized JSON = " + jsonStr);
    }
}

如果您运行此代码,您将得到的唯一序列化错误是No serializer found for class org.json.JSONObject

问题是JSONObject class 的序列化。

ObjectMapper 实例的默认配置是仅访问公共字段或具有公共 getter 的属性。

因此,这是org.json.JSONObject序列化的问题。

解决方法可能很少

  1. 删除JsonObject并改用Map

  2. 通过添加以下内容配置您的 object 映射器以访问私有字段:

     mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

你会看到像这样的 output

{
    "uuid": "15f37c75-9a82-476b-a725-90f3742d3de1",
    "date": 1607961986243,
    "jsonObject": {
        "map": {
            "Age": "Unknown",
            "Name": "John Doe"
        }
    }
}
  1. 最后一个选项是忽略失败的字段(如JSONObject )并序列化剩余的字段。 您可以通过配置 object 映射器来做到这一点,如下所示:

     mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

如果你这样做,你会看到 output 如下所示:

{
    "uuid": "82808d07-47eb-4f56-85ff-7a788158bbb5",
    "date": 1607962486862,
    "jsonObject": {}
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM