JSON.parseObject 构造方法陷阱

JSON.parseObject 构造方法陷阱详解

在使用 FastJSON 的 JSON.parseObject 方法时,构造方法的处理有几个关键陷阱需要注意,这些可能导致反序列化失败或数据丢失。

主要陷阱

1. 无参构造方法缺失陷阱

  • 现象:反序列化时抛出 com.alibaba.fastjson.JSONException: default constructor not found

  • 原因:FastJSON 默认优先尝试调用无参构造方法

  • 解决方案

    java
     
    Copy
     
    Download
    // 添加显式无参构造方法(即使类中没有字段)
    public MyClass() {}

2. 多构造方法歧义陷阱

  • 现象:反序列化结果不符合预期,某些字段为null

  • 原因:当存在多个构造方法时,FastJSON可能选择错误的构造方法

  • 解决方案

    java
     
    Copy
     
    Download
    // 使用@JSONCreator明确指定应该使用的构造方法
    @JSONCreator
    public MyClass(@JSONField(name = "field1") String field1, 
                  @JSONField(name = "field2") int field2) {
        //...
    }

3. 构造方法参数名丢失陷阱

  • 现象:构造方法参数值全部为null或默认值

  • 原因:Java字节码默认不保留参数名(除非编译时加了-parameters参数)

  • 解决方案

    java
     
    Copy
     
    Download
    // 方案1:编译时添加-parameters参数(推荐)
    // 方案2:使用@JSONField注解明确指定参数对应JSON字段
    @JSONCreator
    public MyClass(@JSONField(name = "jsonField1") String param1) {
        //...
    }

4. 不可变对象陷阱

  • 现象:final字段反序列化失败

  • 原因:FastJSON默认先创建对象再通过反射设值,与final字段冲突

  • 解决方案

    java
     
    Copy
     
    Download
    // 必须通过构造方法初始化final字段
    public class Immutable {
        private final String name;
        
        @JSONCreator
        public Immutable(@JSONField(name = "name") String name) {
            this.name = name;
        }
    }

5. 内部类构造陷阱

  • 现象:反序列化内部类时抛出异常

  • 原因:非静态内部类隐含需要外部类实例

  • 解决方案

    java
     
    Copy
     
    Download
    // 方案1:改为静态内部类
    public static class InnerClass {}
    
    // 方案2:提供外部类实例
    ParserConfig.getGlobalInstance().putDeserializer(InnerClass.class, 
        (parser, type, fieldName) -> {
            return outerInstance.new InnerClass();
        });

最佳实践

  1. 显式定义无参构造方法:即使类中有其他构造方法

  2. 对复杂对象使用@JSONCreator:特别是当有无参构造方法但需要通过构造方法初始化时

  3. 编译保留参数名:在Maven/Gradle中配置:

    xml
     
    Copy
     
    Download
     
     
    Run
    <!-- Maven示例 -->
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
            <compilerArgs>
                <arg>-parameters</arg>
            </compilerArgs>
        </configuration>
    </plugin>
  4. 测试不同构造场景:特别是当类有多种构造方法时

  5. 考虑使用Builder模式:对于复杂对象,可以配合自定义反序列化器使用

posted @ 2025-05-08 18:40  lutt123  阅读(203)  评论(0)    收藏  举报