作者:微信小助手
发布时间:2022-01-25T13:26:03
1. 先尝试找空参构造方法和 get\set 方法,如果有,直接利用这两个反序列化。 2. 如果没有,尝试找有参构造方法,但需要通过 @ConstructorProperties 来寻找。 1. 老版本的 fastjson 是不尝试寻找合适的有参构造,除非写了 JSONCreator 注解。 2. jackson 也是不尝试自己寻找,但可以借助 lombok 或用户自己写的 ConstructorProperties 注解。 3. 新版本的 fastjson 比较卷,还会自己尝试通过 asm 的方式强行帮你找到。
 <dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.18</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.3</version>
    </dependency>
</dependencies>package com.flash;
import lombok.AllArgsConstructor;
@ToString
@AllArgsConstructor
public class Student {
    private int age;
}package com.flash;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class TestLombokJackson {
    public static void main(String[] args) throws IOException {
        String json = "{\"age\":1}";
        Student s = new ObjectMapper().readValue(json, Student.class);
        System.out.println(s);
    }
}Student(age=1)
  
 <dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.16.20</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.3</version>
    </dependency>
</dependencies>Exception in thread "main" com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.flash.Student` (although at least one Creator exists): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (String)"{"age":1}"; line: 1, column: 2]
 at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
 at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1342)
 at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1031)
 at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1275)
 at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:325)
 at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159)
 at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001)
 at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992)
 at com.flash.TestLombokJackson.main(TestLombokJackson.java:10)
Process finished with exit code 1
  
  
  
 package com.flash;
import java.beans.ConstructorProperties;
public class Student {
    private int age;
    public String toString() {
        return "Student(age=" + this.age + ")";
    }
    @ConstructorProperties({"age"})
    public Student(int age) {
        this.age = age;
    }
}package com.flash;
public class Student {
    private int age;
    public String toString() {
        return "Student(age=" + this.age + ")";
    }
    public Student(int age) {
        this.age = age;
    }
}
 
 
  
 
 @Override
public Boolean hasCreatorAnnotation(Annotated a) {
    ConstructorProperties props = 
        a.getAnnotation(ConstructorProperties.class);
    if (props != null) {
        return Boolean.TRUE;
    }
    return null;
}protected Object deserializeFromObjectUsingNonDefault(JsonParser p,
        DeserializationContext ctxt) throws IOException {
    ...
    if (_propertyBasedCreator != null) {
        return _deserializeUsingPropertyBased(p, ctxt);
    }
    ...
    return ctxt.handleMissingInstantiator(raw, getValueInstantiator(), p,
            "cannot deserialize from Object value (no delegate- or property-based Creator)");
}
 
 
  
 
  
 
 
  
 
 package com.flash;
import lombok.AllArgsConstructor;
@ToString
@AllArgsConstructor
public class Student {
    private int age;
}package com.flash;
import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
public class TestLombokJackson {
    public static void main(String[] args) throws IOException {
        String json = "{\"age\":1}";
        Student s = JSONObject.parseObject(json, Student.class);
        System.out.println(s);
    }
}Exception in thread "main" com.alibaba.fastjson.JSONException: default constructor not found. class com.flash.Student
 at com.alibaba.fastjson.util.JavaBeanInfo.build(JavaBeanInfo.java:224)
 at com.alibaba.fastjson.parser.ParserConfig.createJavaBeanDeserializer(ParserConfig.java:574)
 at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:491)
 at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(ParserConfig.java:348)
 at com.alibaba.fastjson.parser.DefaultJSONParser.parseObject(DefaultJSONParser.java:639)
 at com.alibaba.fastjson.JSON.parseObject(JSON.java:350)
 at com.alibaba.fastjson.JSON.parseObject(JSON.java:254)
 at com.alibaba.fastjson.JSON.parseObject(JSON.java:467)
 at com.flash.TestLombokJackson.main(TestLombokJackson.java:12)
 
  
 Student(age=1)
  
 
  
 
  
 public static JavaBeanInfo build(...) {
    ...
    // 直接获取默认空参构造
    Constructor[] constructors = clazz.getDeclaredConstructors();
    defaultConstructor = getDefaultConstructor(clazz, constructors);
    ...
    // 默认空参不存在的话
    if (defaultConstructor == null){
        ...
        for (Constructor constructor : constructors) {
            ...
            // 通过 asm 方式寻找参数名
            paramNames = ASMUtils.lookupParameterNames(constructor);
            ...
        }
        ...
        // 找到了就可以正常返回了
        if (paramNames != null && ...) {
            ...
            return new JavaBeanInfo(...);
        }
        // 原来是直接到下面这句,不经过上面 asm 寻找名的过程
        throw new JSONException("default constructor not found. " + clazz);
    }
    ...
}