zoukankan      html  css  js  c++  java
  • 使用FastJson parseObject方法时,json字符串解析成对象后,部分属性丢失问题处理

    出现此类问题的原因会有多种, 本文仅介绍发现的一种情况,不一定适用所有的场景

    情景:

      JavaBean 中没有默认的构造方法

    例如:

    public class Student{
    
    
        public static void main(String[] args) {
            String jsonStr = "{"id":1,"name":"Ming","age":18,"phone":"23333333333","address":"杭州"}";
            Student student = JSON.parseObject(jsonStr, Student.class);
            System.out.println(JSON.toJSONString(student));
        }
    
    
        private Long id;
        private String name;
        private Integer age;
        private String address;
        private String phone;
    
        public Student(Long id, String name,String phone) {
            this.id = id;
            this.name = name;
            this.phone = phone;
        }
    
    
        public Student(Long id, String name, Integer age, String address) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.address = address;
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getPhone() {
            return phone;
        }
    
        public void setPhone(String phone) {
            this.phone = phone;
        }
    }

    运行结果: {"address":"杭州","age":18,"id":1,"name":"Ming"}

    此时解析成对象后,会丢失phone属性.虽然有一个构造器是带有phone字段的.

    原因:

      FastJson 创建 JavaBean,调用了

    #会调用以下构造方法
    new JavaBeanDeserializer(this,clazz,type);
    
    #构造方法详情
    public JavaBeanDeserializer(ParserConfig config, Class<?> clazz, Type type){
            this(config //
                    , JavaBeanInfo.build(clazz, type, config.propertyNamingStrategy, config.fieldBased, config.compatibleWithJavaBean, config.isJacksonCompatible())
            );
        }
    
    #build方法确定使用哪个构造器的代码片段
    for (Constructor constructor : constructors) {
                            Class<?>[] parameterTypes = constructor.getParameterTypes();
    
                            if (className.equals("org.springframework.security.web.authentication.WebAuthenticationDetails")) {
                                if (parameterTypes.length == 2 && parameterTypes[0] == String.class && parameterTypes[1] == String.class) {
                                    creatorConstructor = constructor;
                                    creatorConstructor.setAccessible(true);
                                    paramNames = ASMUtils.lookupParameterNames(constructor);
                                    break;
                                }
                            }
    
                            if (className.equals("org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken")) {
                                if (parameterTypes.length == 3
                                        && parameterTypes[0] == Object.class
                                        && parameterTypes[1] == Object.class
                                        && parameterTypes[2] == Collection.class) {
                                    creatorConstructor = constructor;
                                    creatorConstructor.setAccessible(true);
                                    paramNames = new String[] {"principal", "credentials", "authorities"};
                                    break;
                                }
                            }
    
                            if (className.equals("org.springframework.security.core.authority.SimpleGrantedAuthority")) {
                                if (parameterTypes.length == 1
                                        && parameterTypes[0] == String.class) {
                                    creatorConstructor = constructor;
                                    paramNames = new String[] {"authority"};
                                    break;
                                }
                            }
    
                            //
    
    
                            boolean is_public = (constructor.getModifiers() & Modifier.PUBLIC) != 0;
                            if (!is_public) {
                                continue;
                            }
                            String[] lookupParameterNames = ASMUtils.lookupParameterNames(constructor);
                            if (lookupParameterNames == null || lookupParameterNames.length == 0) {
                                continue;
                            }
    
                            if (creatorConstructor != null
                                    && paramNames != null && lookupParameterNames.length <= paramNames.length) {
                                continue;
                            }
    
                            paramNames = lookupParameterNames;
                            creatorConstructor = constructor;
                        }

    # 可以看到这句判断,会迭代当前JavaBean的所有构造器,并取到构造器方法列表最长的那个构造器,作为JSON解析的构造器.

    if (creatorConstructor != null && paramNames != null && lookupParameterNames.length <= paramNames.length) {
        continue;
    }


    根据以上代码可以看出,为什么丢失了phone属性.方法形参列表最长的构造器是没有phone属性的

    解决方法:

      1.新增默认的构造器

           2.方法形参列表最长的构造器中新增phone属性(如果代码已运行很久,建议新增构造器,方法形参列表最长,且包含phone字段)

  • 相关阅读:
    程序员修神之路--容器技术为什么会这么流行
    程序员修神之路--kubernetes是微服务发展的必然产物
    程序员修神之路--有状态的服务其实可以做更多的事情
    程序员修神之路--要想做好微服务架构,并非易事!
    程序员修神之路--为什么有了SOA,我们还用微服务?
    程序员过关斩将--数据库的乐观锁和悲观锁并非真实的锁
    程序员修神之路--设计一套RPC框架并非易事
    计算机的诞生和简史
    记一次Linux修改MySQL配置不生效的问题
    为什么大多数公司都不重视技术?
  • 原文地址:https://www.cnblogs.com/lzzRye/p/12625800.html
Copyright © 2011-2022 走看看