fastjson2 icon indicating copy to clipboard operation
fastjson2 copied to clipboard

[QUESTION]复杂的嵌套bean反序列化无法设置默认值

Open q605450469 opened this issue 2 years ago • 5 comments

依赖版本 jdk1.8.0_162

<dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.28</version>
</dependency>
<dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.16.22</version>
</dependency>
<dependency>
      <groupId>com.alibaba.fastjson2</groupId>
      <artifactId>fastjson2</artifactId>
      <version>2.0.4</version>
</dependency>

DTO

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestDTO {
    
    private String name;
    private int age;
    private SubDTO subDTO = new SubDTO();

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class SubDTO {
        private String id;
        private String nickName;
        private ThiDTO thiDTO = new ThiDTO();
        private FouDTO fouDTO = new FouDTO();
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ThiDTO {
    private String h;
    private String w;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FouDTO {
    private String p;
    private String t;
}

json

{
    "name": "123",
    "age": 3,
    "subDTO": {
        "id": "222",
        "thiDTO": {
            "h": "444"
        }
    }
}

运行代码

String s = "{\"name\":\"123\",\"age\":3,\"subDTO\":{\"id\":\"222\",\"thiDTO\":{\"h\":\"444\"}}}";
TestDTO testDTO2 = JSON.parseObject(s, TestDTO.class, JSONReader.Feature.SupportSmartMatch);
TestDTO testDTO1 = com.alibaba.fastjson.JSON.parseObject(s, TestDTO.class);
System.out.println("testDTO2 = " + testDTO2);
System.out.println("testDTO1 = " + testDTO1);

执行结果

testDTO2 = TestDTO(name=123, age=3, subDTO=TestDTO.SubDTO(id=222, nickName=null, thiDTO=ThiDTO(h=444, w=null), fouDTO=null))
testDTO1 = TestDTO(name=123, age=3, subDTO=TestDTO.SubDTO(id=222, nickName=null, thiDTO=ThiDTO(h=444, w=null), fouDTO=FouDTO(p=null, t=null)))

其中SubDTO是TestDTO的成员内部类,ThiDTO与FouDTO与TestDTO同包类,这种嵌套类结构在使用1.2.x版本可以实现全部成员类的默认值。但是在2版本无法实现fouDTO的默认值。 请问除了将SubDTO从成员内部类提出来外还有别的方式可以实现默认值吗?

q605450469 avatar May 27 '22 10:05 q605450469

你好, 默认值是有的, 但是构造函数里被覆盖为null, 在fastjson2中有两种解决方法

  1. SubDTO 改为静态内部类
        @Data
        @AllArgsConstructor
        @NoArgsConstructor
        public static class SubDTO2 {
            private String id;
            private String nickName;
            private ThiDTO thiDTO = new ThiDTO();
            private FouDTO fouDTO = new FouDTO();
        }
  1. SubDTO去掉@AllArgsConstructor注解
        @Data
        @NoArgsConstructor
        public class SubDTO {
            private String id;
            private String nickName;
            private ThiDTO thiDTO = new ThiDTO();
            private FouDTO fouDTO = new FouDTO();
        }

kraity avatar May 29 '22 03:05 kraity

你好, 默认值是有的, 但是构造函数里被覆盖为null, 在fastjson2中有两种解决方法

因为为SubDTO 非静态 内部类时, 创建SubDTO是通过构造是需要传入父TestDTO, 标记@AllArgsConstructor, fastjson2优先使用这个注解创建的构造参数, 那么在JSON文本中没有对应的fouDTO 时, 那么反序列化相当于null, 那么传入构造函数时, SubDTO.fouDTO 本有值的, 缺被覆盖为了null

kraity avatar May 29 '22 03:05 kraity

你好, 默认值是有的, 但是构造函数里被覆盖为null, 在fastjson2中有两种解决方法

因为为SubDTO 非静态 内部类时, 创建SubDTO是通过构造是需要传入父TestDTO, 标记@AllArgsConstructor, fastjson2优先使用这个注解创建的构造参数, 那么在JSON文本中没有对应的fouDTO 时, 那么反序列化相当于null, 那么传入构造函数时, SubDTO.fouDTO 本有值的, 缺被覆盖为了null

@kraity 感谢解答,目前已经可以达成期望结果。但是我们项目升级希望尽可能低的对原有代码做变更,请问之后会有计划在这方面做兼容或者优化吗?

q605450469 avatar May 30 '22 09:05 q605450469

要支持还比较麻烦,我还要再想想

wenshao avatar Sep 18 '22 13:09 wenshao

https://oss.sonatype.org/content/repositories/snapshots/com/alibaba/fastjson2/fastjson2/2.0.15-SNAPSHOT/ 问题已修复,请帮忙用2.0.15-SNAPSHOT验证,2.0.15版本预计在10月7日前发布

wenshao avatar Sep 19 '22 12:09 wenshao

https://github.com/alibaba/fastjson2/releases/tag/2.0.15 问题修复,请用新版本

wenshao avatar Oct 05 '22 06:10 wenshao