[alibaba/fastjson]fastjson对父类中有同名下划线开头的字段取值错误的问题

2024-05-23 609 views
2
版本
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.67</version>
        </dependency>
问题

发现了个fastjson转换的bug。示例代码如下:

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * @author superlee
 * @since 2020-05-22
 */
public class TestStatus {

    public static void main(String[] args) throws JsonProcessingException {
        Son son = new TestStatus.Son();
        son.setStatus("status");
        ObjectMapper objectMapper = new ObjectMapper();
        System.out.println("======>fastjson<======");
        System.out.println(JSON.toJSONString(son));

        System.out.println("======>jackson<======");
        System.out.println(objectMapper.writeValueAsString(son));
    }

    static class Parent {
        private String _status;

        public String get_status() {
            return _status;
        }

        public void set_status(String _status) {
            this._status = _status;
        }
    }

    static class Son extends Parent {

        private String status;

        public String getStatus() {
            return status;
        }

        public void setStatus(String status) {
            this.status = status;
        }
    }
}

输出如下

======>fastjson<======
{}
======>jackson<======
{"_status":null,"status":"status"}

目前找到的原因是反射获取son对象getStatus方法时,获取错误,取到了父类get_status方法。导致获取值的时候返回为null。 image 对象的status字段是有值的,但是在fieldSerializer.getPropertyValueDirect(object)的时候返回的是null, image 反射获取status的get方法时,取到了父类get_status方法。导致返回位null。

回答

2

加一行: son.set_status("parent"); 然后再测试一下

7

加一行: son.set_status("parent"); 然后再测试一下

image image 还是获取get方法错误,无法区分带有下划线的字段

7

是有Bug,问题出在TypeUtils的1965行,之前是methodName.charAt(3) 为"_"时,首先尝试substring(4) 如果在之前缓存的字段中找到了,那么则直接执行。这个时候问题就来来,substring(4) 把下划线去掉了,但是在子类中 有一个相同的Status,所以是在缓存的字段里找到了。但是这个Status是空的。所以就直接返回了。

本身单独的一个类中的一个字段涉及下划线的也有问题,但是之前的代码是如果 substring(4) 没找到,则使用substring(3)。所以只有一个下划线字段时是没毛病的。

我改的代码则是先使用substring(3),如果在缓存中匹配到这个字段的话就执行。否则再去匹配substring(4)

1

是有Bug,问题出在TypeUtils的1965行,之前是methodName.charAt(3) 为"_"时,首先尝试substring(4) 如果在之前缓存的字段中找到了,那么则直接执行。这个时候问题就来来,substring(4) 把下划线去掉了,但是在子类中 有一个相同的Status,所以是在缓存的字段里找到了。但是这个Status是空的。所以就直接返回了。

本身单独的一个类中的一个字段涉及下划线的也有问题,但是之前的代码是如果 substring(4) 没找到,则使用substring(3)。所以只有一个下划线字段时是没毛病的。

我改的代码则是先使用substring(3),如果在缓存中匹配到这个字段的话就执行。否则再去匹配substring(4)

好的,谢谢。项目的代码比较古老,有字段命名不规范的地方,不是很好改了,然后就出现了序列化的时候字段丢失的问题。