FastJSON字段名智能匹配机制与解决方案

24 年 4 月 15 日 星期一
391 字
2 分钟

想要序列化这样的JSONArray

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

对应的实体对象

java
@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字段,具体生成打印数据如下

java
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);
    }
}

text
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关闭智能匹配即可
java
    @JSONType(parseFeatures = Feature.DisableFieldSmartMatch)
    public static class ATest {
        private int a_id;
    }
  1. 指定字段加上Feature.DisableFieldSmartMatch关闭智能匹配即可
java
    public class ATest {
        @JSONField(parseFeatures = Feature.DisableFieldSmartMatch)
        private int a_id;
    }

参考 wiki

文章标题:FastJSON字段名智能匹配机制与解决方案

文章作者:Jinx

文章链接:https://blog.mytest.cc/posts/fastjson-field-smart-match-solution[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。