Jinx

一只奶牛猫

JSON反序列化时字段名自动忽略下划线

发布于 # fastjson # java

想要序列化这样的JSONArray

[
    {
        "_checked": true,
        "checked": 0,
        "key": "department",
        "label": "部门",
        "sortedEnabled": 0,
        "sortedType": ""
    },
    {
        "_checked": true,
        "checked": 2,
        "key": "username",
        "label": "用户名",
        "sortedEnabled": 0,
        "sortedType": ""
    }
]

对应的实体对象

@Data
public class QueryOrderDTO {
    /**
     * 字段中文名
     */
    private String label;
    /**
     * 字段英文名
     */
    private String key;

    /**
     * 是否勾选 0勾选 1不勾 2默认
     */
    private Integer checked;

    /**
     * 排序开关 0-false 1-true
     */
    private Integer sortedEnabled;

    /**
     * 排序开关 ASC/DESC
     */
    private String sortedType;
}

发现因为增加了_checked字符,导致序列化只能匹配到_checked字段,具体生成打印数据如下

public class JSONParseUtil {
    public static void main(String[] args) {
        String json = "[{\"_checked\":true,\"checked\":0,\"key\":\"department\",\"label\":\"部门\",\"sortedEnabled\":0,\"sortedType\":\"\"},{\"_checked\":true,\"checked\":2,\"key\":\"username\",\"label\":\"用户名\",\"sortedEnabled\":0,\"sortedType\":\"\"},{\"_checked\":true,\"checked\":2,\"key\":\"question\",\"label\":\"问题\",\"sortedEnabled\":0,\"sortedType\":\"\"},{\"_checked\":true,\"checked\":2,\"key\":\"answer\",\"label\":\"答案\",\"sortedEnabled\":0,\"sortedType\":\"\"},{\"_checked\":false,\"checked\":1,\"key\":\"employeeId\",\"label\":\"员工编号\",\"sortedEnabled\":0,\"sortedType\":\"\"},{\"_checked\":false,\"checked\":1,\"key\":\"directory\",\"label\":\"目录\",\"sortedEnabled\":0,\"sortedType\":\"\"},{\"_checked\":true,\"checked\":0,\"key\":\"referenceFiles\",\"label\":\"参考文件\",\"sortedEnabled\":0,\"sortedType\":\"\"},{\"_checked\":true,\"checked\":0,\"key\":\"dislikeReason\",\"label\":\"点踩原因\",\"sortedEnabled\":0,\"sortedType\":\"\"},{\"_checked\":true,\"checked\":0,\"key\":\"feedbackStatus\",\"label\":\"反馈状态\",\"sortedEnabled\":0,\"sortedType\":\"\"},{\"_checked\":true,\"checked\":0,\"key\":\"questionTime\",\"label\":\"提问时间\",\"sortedEnabled\":0,\"sortedType\":\"\"}]";

        List<QueryOrderDTO> queryOrderDTOS =
                JSON.parseArray(json, QueryOrderDTO.class);
        queryOrderDTOS.forEach(System.out::println);
    }
}

QueryOrderDTO(label=部门, key=department, checked=1, sortedEnabled=0, sortedType=)
QueryOrderDTO(label=用户名, key=username, checked=1, sortedEnabled=0, sortedType=)

fastjson把_checked当作checked处理了,忽略了前面的下划线,导致真正的checked字段没有被获取到。具体原因参考GitHub的Issuehttps://github.com/alibaba/fastjson/issues/2026

https://github.com/alibaba/fastjson/issues/3035

解决办法参考:https://github.com/alibaba/fastjson/issues/3549

parse 默认开启了FieldSmartMatch, 处理key时会忽略掉下划线,因此在解析时,误把aid当做a_id进行解析,value应该为int但aid对应的value却是str,因此会出现类型转换异常。

解决办法:

  1. 类注解加上Feature.DisableFieldSmartMatch关闭智能匹配即可
    @JSONType(parseFeatures = Feature.DisableFieldSmartMatch)
    public static class ATest {
        private int a_id;
    }
  1. 指定字段加上Feature.DisableFieldSmartMatch关闭智能匹配即可
    public class ATest {
        @JSONField(parseFeatures = Feature.DisableFieldSmartMatch)
        private int a_id;
    }

参考 wiki