FastJson序列化和反序列化问题记录

勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

导读:本篇文章讲解 FastJson序列化和反序列化问题记录,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

序列化与反序列化问题

调用外部接口,http://100.111.55.67:9999/cmdb/v0.2.0/departments?page_size=1000,返回数据格式如下:

{
    "code": 0,
    "content": [
        {
            "id": "4561",
            "level": 1,
            "name": "业务后台",
            "parent_id": "1",
            "parent_name": "信仰科技"
        }
    ],
    "msg": "success"
}

居然是下划线命名的。现在需要将该接口包一层,然后暴露给前端。前后端的开发规范是返回驼峰命名的数据。

直接使用JSONObject解析也行,但是较好的方式是定义一个POJO,并加上注解@JSONField

@Data
public class CmdbModel {
    private Integer id;
    private Integer level;
    private String name;
    @JSONField(name = "parent_id")
    private Integer parentId;
    @JSONField(name = "parent_name")
    private String parentName;
}
@Data
private static class Resp {
    private Integer code;
    private List<CmdbModel> content;
    private String msg;
}

Service层代码就是一个简单的HTTP Get,然后JSONObject反序列化解析定义的POJO class类。

@Override
public List<CmdbModel> listDepartment() {
    String url = cmdbUrl + DEPARTMENTS;
    try {
        Resp resp = JSONObject.parseObject(HttpUtil.doGet(url), Resp.class);
        if (resp != null && resp.getCode() == 0) {
            return resp.getContent();
        }
    } catch (Exception e) {
        log.error("listDepartment failed: ", e);
    }
    return Collections.emptyList();
}

此处返回的数据肯定就是驼峰命名的。

Controller层接口

@RequestMapping("listDepartment")
public String listDepartment() {
    return JSONObject.toJSONString(ServiceUtil.returnSuccessData(cmdbService.listDepartment()));
}

问题:Postman调用此接口,发现数据居然和最原始的外部接口的数据一样,是下划线命名。

使用的依赖及其版本号:

<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>fastjson</artifactId>
     <version>1.2.73</version>
 </dependency>

原因:ServiceUtil.returnSuccessData返回的是Map<String, Object>类型的数据,JSONObject.toJSONString将Map序列化时,发现有@JSONField注解,然后又把驼峰命名转换为下划线命名。

能不能从@JSONField注解入手解决问题?

看看@JSONField源码:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
public @interface JSONField {
    int ordinal() default 0;

    String name() default "";

    String format() default "";

    boolean serialize() default true;

    boolean deserialize() default true;

    SerializerFeature[] serialzeFeatures() default {};

    Feature[] parseFeatures() default {};

    String label() default "";

    boolean jsonDirect() default false;

    Class<?> serializeUsing() default Void.class;

    Class<?> deserializeUsing() default Void.class;

    String[] alternateNames() default {};

    boolean unwrapped() default false;

    String defaultValue() default "";
}

期望效果:反序列化时把下划线反序列化为驼峰命名,随后返回前端的String需要经过一次序列化过程,序列化时保留驼峰命名。

实验:
注解加上serialize配置得到:@JSONField(name = "parent_id", serialize = false),直接忽视此字段。

看样子,无法从此注解入手解决问题???

另外,不知道另外一个据说比fastjson更强大,版本发布频率强力碾压fastjson的JSON工具jackson,怎么解决这个”问题”?

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.1</version>
</dependency>

解决方法:再定义一个VO,CmdbVo的字段和CmdbModel的字段一模一样,只是没有@JSONField注解,然后使用BeanUtils进行数据赋值:

List<CmdbVo> cmdbVoList = Lists.newArrayListWithCapacity(resp.getContent().size());
resp.getContent().forEach(x -> {
    CmdbVo vo = new CmdbVo();
    BeanUtils.copyProperties(x, vo);
    cmdbVoList.add(vo);
});

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/142152.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!