Java中的JSON序列化和反序列化
创始人
2025-05-31 09:46:42

文章目录

  • Java 和 JSON 序列化
    • JSON 简介
      • JSON 是什么
      • JSON 标准
      • JSON 优缺点
      • JSON 工具
      • Java JSON 库
      • JSON 编码指南
    • Fastjson 应用
      • 添加 maven 依赖
      • Fastjson API
        • 定义 Bean
        • 序列化
        • 反序列化
      • Fastjson 注解
        • `@JSONField`
        • `@JSONType`
    • Jackson 应用
      • 添加 maven 依赖
      • Jackson API
        • 序列化
        • 反序列化
        • 容器的序列化和反序列化
      • Jackson 注解
        • `@JsonProperty`
        • `@JsonIgnoreProperties` 和 `@JsonIgnore`
        • `@JsonCreator`
        • `@JsonPropertyOrder`
    • Gson 应用
      • 添加 maven 依赖
      • Gson API
        • 序列化
        • 反序列化
        • GsonBuilder
      • Gson 注解
        • `@Since`
        • `@SerializedName`
    • 参考资料

在这里插入图片描述

Java 和 JSON 序列化

JSON(JavaScript Object Notation)是一种基于文本的数据交换格式。几乎所有的编程语言都有很好的库或第三方工具来提供基于 JSON 的 API 支持,因此你可以非常方便地使用任何自己喜欢的编程语言来处理 JSON 数据。

JSON 简介

JSON 是什么

JSON 起源于 1999 年的 JS 语言规范 ECMA262 的一个子集,后来 2003 年作为一个数据格式ECMA404(404???)发布。
2006 年,作为 rfc4627 发布,这时规范增加到 18 页,去掉没用的部分,十页不到。

JSON 的应用很广泛,这里有超过 100 种语言下的 JSON 库:json.org。

更多的可以参考这里,关于 json 的一切。

JSON 标准

这是最简单标准规范之一:

  • 只有两种结构:对象内的键值对集合结构和数组,对象用 {} 表示、内部是 "key":"value",数组用 [] 表示,不同值用逗号分开
  • 基本数值有 7 个: false / null / true / object / array / number / string
  • 再加上结构可以嵌套,进而可以用来表达复杂的数据
  • 一个简单实例:
{"Image": {"Width": 800,"Height": 600,"Title": "View from 15th Floor","Thumbnail": {"Url": "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","Height": 125,"Width": "100"},"IDs": [116, 943, 234, 38793]}
}

JSON 优缺点

优点:

  • 基于纯文本,所以对于人类阅读是很友好的。
  • 规范简单,所以容易处理,开箱即用,特别是 JS 类的 ECMA 脚本里是内建支持的,可以直接作为对象使用。
  • 平台无关性,因为类型和结构都是平台无关的,而且好处理,容易实现不同语言的处理类库,可以作为多个不同异构系统之间的数据传输格式协议,特别是在 HTTP/REST 下的数据格式。

缺点:

  • 性能一般,文本表示的数据一般来说比二进制大得多,在数据传输上和解析处理上都要更影响性能。
  • 缺乏 schema,跟同是文本数据格式的 XML 比,在类型的严格性和丰富性上要差很多。XML 可以借由 XSD 或 DTD 来定义复杂的格式,并由此来验证 XML 文档是否符合格式要求,甚至进一步的,可以基于 XSD 来生成具体语言的操作代码,例如 apache xmlbeans。并且这些工具组合到一起,形成一套庞大的生态,例如基于 XML 可以实现 SOAP 和 WSDL,一系列的 ws-*规范。但是我们也可以看到 JSON 在缺乏规范的情况下,实际上有更大一些的灵活性,特别是近年来 REST 的快速发展,已经有一些 schema 相关的发展(例如理解 JSON Schema,使用 JSON Schema, 在线 schema 测试),也有类似于 WSDL 的WADL出现。

JSON 工具

  • 使用 JSON 实现 path 查询操作(类似 XML-PATH):JsonPATH

  • 在线查询工具:JsonPATH、 json.cn

  • 格式化工具:jsbeautifier

  • chrome 插件:5 个 Json View 插件

Java JSON 库

Java 中比较流行的 JSON 库有:

  • Fastjson - 阿里巴巴开发的 JSON 库,性能十分优秀。
  • Jackson - 社区十分活跃且更新速度很快。Spring 框架默认 JSON 库。
  • Gson - 谷歌开发的 JSON 库,目前功能最全的 JSON 库 。

从性能上来看,一般情况下:Fastjson > Jackson > Gson

JSON 编码指南

遵循好的设计与编码风格,能提前解决 80%的问题,推荐 Google JSON 风格指南。

  • 英文版Google JSON Style Guide:https://google.github.io/styleguide/jsoncstyleguide.xml
  • 中文版Google JSON 风格指南:https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.md

简单摘录如下:

  • 属性名和值都是用双引号,不要把注释写到对象里面,对象数据要简洁
  • 不要随意结构化分组对象,推荐是用扁平化方式,层次不要太复杂
  • 命名方式要有意义,比如单复数表示
  • 驼峰式命名,遵循 Bean 规范
  • 使用版本来控制变更冲突
  • 对于一些关键字,不要拿来做 key
  • 如果一个属性是可选的或者包含空值或 null 值,考虑从 JSON 中去掉该属性,除非它的存在有很强的语义原因
  • 序列化枚举类型时,使用 name 而不是 value
  • 日期要用标准格式处理
  • 设计好通用的分页参数
  • 设计好异常处理

JSON API与 Google JSON 风格指南有很多可以相互参照之处。

JSON API是数据交互规范,用以定义客户端如何获取与修改资源,以及服务器如何响应对应请求。

JSON API 设计用来最小化请求的数量,以及客户端与服务器间传输的数据量。在高效实现的同时,无需牺牲可读性、灵活性和可发现性。

Fastjson 应用

添加 maven 依赖

com.alibabafastjsonx.x.x

Fastjson API

定义 Bean

Group.java

public class Group {private Long       id;private String     name;private List users = new ArrayList();
}

User.java

public class User {private Long   id;private String name;
}

初始化 Bean

Group group = new Group();
group.setId(0L);
group.setName("admin");User guestUser = new User();
guestUser.setId(2L);
guestUser.setName("guest");User rootUser = new User();
rootUser.setId(3L);
rootUser.setName("root");group.addUser(guestUser);
group.addUser(rootUser);

序列化

String jsonString = JSON.toJSONString(group);
System.out.println(jsonString);

反序列化

Group bean = JSON.parseObject(jsonString, Group.class);

Fastjson 注解

@JSONField

扩展阅读:更多 API 使用细节可以参考:JSONField 用法,这里介绍基本用法。

可以配置在属性(setter、getter)和字段(若属性是私有的,必须有set*方法。否则无法反序列化)上。

@JSONField(name="ID")
public int getId() {return id;}// 配置date序列化和反序列使用yyyyMMdd日期格式
@JSONField(format="yyyyMMdd")
public Date date1;// 不序列化
@JSONField(serialize=false)
public Date date2;// 不反序列化
@JSONField(deserialize=false)
public Date date3;// 按ordinal排序
@JSONField(ordinal = 2)
private int f1;@JSONField(ordinal = 1)
private int f2;

@JSONType

  • 自定义序列化:ObjectSerializer
  • 子类型处理:SeeAlso

JSONType.alphabetic 属性: fastjson 缺省时会使用字母序序列化,如果你是希望按照 java fields/getters 的自然顺序序列化,可以配置 JSONType.alphabetic,使用方法如下:

@JSONType(alphabetic = false)
public static class B {public int f2;public int f1;public int f0;
}

Jackson 应用

扩展阅读:更多 API 使用细节可以参考 jackson-databind 官方说明

添加 maven 依赖

com.fasterxml.jackson.corejackson-databind2.9.8

Jackson API

序列化

ObjectMapper mapper = new ObjectMapper();mapper.writeValue(new File("result.json"), myResultObject);
// or:
byte[] jsonBytes = mapper.writeValueAsBytes(myResultObject);
// or:
String jsonString = mapper.writeValueAsString(myResultObject);

反序列化

ObjectMapper mapper = new ObjectMapper();MyValue value = mapper.readValue(new File("data.json"), MyValue.class);
// or:
value = mapper.readValue(new URL("http://some.com/api/entry.json"), MyValue.class);
// or:
value = mapper.readValue("{\"name\":\"Bob\", \"age\":13}", MyValue.class);

容器的序列化和反序列化

Person p = new Person("Tom", 20);
Person p2 = new Person("Jack", 22);
Person p3 = new Person("Mary", 18);List persons = new LinkedList<>();
persons.add(p);
persons.add(p2);
persons.add(p3);Map map = new HashMap<>();
map.put("persons", persons);String json = null;
try {json = mapper.writeValueAsString(map);
} catch (JsonProcessingException e) {e.printStackTrace();
}

Jackson 注解

扩展阅读:更多注解使用细节可以参考 jackson-annotations 官方说明

@JsonProperty

public class MyBean {private String _name;// without annotation, we'd get "theName", but we want "name":@JsonProperty("name")public String getTheName() { return _name; }// note: it is enough to add annotation on just getter OR setter;// so we can omit it herepublic void setTheName(String n) { _name = n; }
}

@JsonIgnoreProperties@JsonIgnore

// means that if we see "foo" or "bar" in JSON, they will be quietly skipped
// regardless of whether POJO has such properties
@JsonIgnoreProperties({ "foo", "bar" })
public class MyBean {// will not be written as JSON; nor assigned from JSON:@JsonIgnorepublic String internal;// no annotation, public field is read/written normallypublic String external;@JsonIgnorepublic void setCode(int c) { _code = c; }// note: will also be ignored because setter has annotation!public int getCode() { return _code; }
}

@JsonCreator

public class CtorBean {public final String name;public final int age;@JsonCreator // constructor can be public, private, whateverprivate CtorBean(@JsonProperty("name") String name,@JsonProperty("age") int age){this.name = name;this.age = age;}
}

@JsonPropertyOrder

alphabetic 设为 true 表示,json 字段按自然顺序排列,默认为 false。

@JsonPropertyOrder(alphabetic = true)
public class JacksonAnnotationBean {}

Gson 应用

详细内容可以参考官方文档:Gson 用户指南

添加 maven 依赖

com.google.code.gsongson2.8.6

Gson API

序列化

Gson gson = new Gson();
gson.toJson(1);            // ==> 1
gson.toJson("abcd");       // ==> "abcd"
gson.toJson(10L); // ==> 10
int[] values = { 1 };
gson.toJson(values);       // ==> [1]

反序列化

int i1 = gson.fromJson("1", int.class);
Integer i2 = gson.fromJson("1", Integer.class);
Long l1 = gson.fromJson("1", Long.class);
Boolean b1 = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"abc\"", String.class);
String[] anotherStr = gson.fromJson("[\"abc\"]", String[].class);

GsonBuilder

Gson 实例可以通过 GsonBuilder 来定制实例化,以控制其序列化、反序列化行为。

Gson gson = new GsonBuilder().setPrettyPrinting().setDateFormat("yyyy-MM-dd HH:mm:ss").excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE).create();

Gson 注解

@Since

@Since 用于控制对象的序列化版本。示例:

public class VersionedClass {@Since(1.1) private final String newerField;@Since(1.0) private final String newField;private final String field;public VersionedClass() {this.newerField = "newer";this.newField = "new";this.field = "old";}
}VersionedClass versionedObject = new VersionedClass();
Gson gson = new GsonBuilder().setVersion(1.0).create();
String jsonOutput = gson.toJson(versionedObject);
System.out.println(jsonOutput);
System.out.println();gson = new Gson();
jsonOutput = gson.toJson(versionedObject);
System.out.println(jsonOutput);

@SerializedName

@SerializedName 用于将类成员按照指定名称序列化、反序列化。示例:

private class SomeObject {@SerializedName("custom_naming") private final String someField;private final String someOtherField;public SomeObject(String a, String b) {this.someField = a;this.someOtherField = b;}
}

参考资料

  • 官方
    • Fastjson Github
    • Gson Github
    • jackson 官方文档
    • jackson-databind
  • 文章
    • http://www.json.org/json-zh.html
    • json 的 RFC 文档
    • JSON 最佳实践
    • 【简明教程】JSON

相关内容

热门资讯

特朗普“大漂亮”法案中埋着“资... 面对隐藏在《大漂亮法案》中的第899条税收条款,大摩警告华尔街面临史上最大“资本税”冲击。华尔街见闻...
创新药年内出海交易总额超455... 6月首个交易日,港股市场开盘走强,医药股上涨。相关ETF方面,港股创新药ETF(159567)盘初上...
康方生物之困 康方生物之困 康... 当潮水涨起,裸泳者又行了?不要忘记时代的眼泪。据中信建投2022年8月统计,2004-2018年间通...
王石的野心与万科的现实,折射地... 文|晓沐 出品|天下财道当74岁的王石在朋友圈敲下“岂能推卸责任”时,深圳湾的海风正掠过万科总部30...
“苏超”霸屏,中国可以靠江苏搞... 01 经济独立,城市人格独立最近一段时间,无相君的朋友圈和微信群都被“苏超”霸屏了。几乎每天一个热搜...
年轻人"花式搞钱&q... 当银行利率跑不赢奶茶涨价速度,这届年轻人的投资战场早已从K线图蔓延到像素世界和二次元谷圈。当传统理财...
两市融资余额较上一日减少81.... 截至5月30日,上交所融资余额报9050.66亿元,较前一交易日减少33.17亿元;深交所融资余额报...
深证成指、创业板指、深证100...   中新经纬6月3日电 深交所网站3日发布公告,调整深证成指、创业板指、深证100等指数样本股。  ...
“商文旅”融合催热假日经济 “... 端午期间,北京、湖北等地开展了丰富多彩特色活动,吸引了不少市民游客前来消费,“商文旅”融合模式成为全...
酸奶不行了?我们盘点了盒马67... 作者 | 杜仲 编辑 | 紫苏 来源 | 观潮新消费(ID:TideSight) 原奶价格跌跌不休、...
黄金、原油大涨 当地时间6月2日,美股三大指数均小幅收涨。美国科技“七巨头”收盘多数上涨。美股中概股多数上涨,纳斯达...
爷爷,你以前真的有过一枚比特币... 一、不是一句玩笑,而是一次认真的提议 “六一儿童节,给孩子留一枚比特币。” 这句热梗刷屏朋友圈...
两市第一“牛股”,三年暴涨15... 在5月30日股价创下历史新高后,惠城环保2022年11月以来的累计涨幅超过15倍,系同时间段A股市场...
华尔街到陆家嘴精选丨美国核心通... ①美国核心通胀指标放缓至四年低位 美联储理事沃勒称今年晚些时候有望降息美国4月核心PCE价格指数同比...
天下道源在亳州,中国酒道看古井... 鲁迅先生曾说:“中国根柢全在道教……以此读史,有多种问题可迎刃而解”,这是中国人信仰道家文化的写照,...
中金:端午节后A股走势或阶段性... 中金公司研报称,综合内外部因素,市场或维持震荡格局。风格层面,得益于流动性充裕与科技叙事催化,中小盘...
在县城门诊,看见底层人群的医疗... 在县城的门诊,那是一幅真实而令人心酸的画面。这里汇聚着底层人群,他们面色疲惫,眼中透露出对健康的渴望...
哪吒汽车,注定掉队 哪吒汽车,... 定焦One(dingjiaoone)原创特约作者 | 胡锟编辑 | 魏佳从登顶新势力销量冠军,到几乎...
盘前情报|工信部:加大汽车行业... 上周A股过去一周(5月26日—5月30日)A股三大指数集体下跌。截至5月30日收盘,上证指数报334...
“苏超”爆火:比赛第一,友谊第... “苏超”爆火,这句“比赛第一,友谊第十四”着实展现了其独特魅力。在苏超的赛场上,选手们全力以赴,每一...
十大券商看后市|A股仍处修复行... A股进入6月交易时间,市场行情将如何演绎呢?澎湃新闻搜集了10家券商的观点,大部分券商认为,中国基本...
特朗普欲将钢铝关税翻倍至50%... 智通财经APP获悉,在美国总统唐纳德·特朗普表示将对铝和钢铁的关税提高一倍至50%后,美国铝和钢铁期...
健康之路,难撑440亿估值 医... 大健康板块已经走出低谷,板块个股估值迎来了大规模的修复行情。6月2日,港股数字健康医疗服务平台公司健...
白天当医生,晚上做游戏,80后... 在当今时代,有这样一位独特的 80 后。白天,他身着白大褂,穿梭在医院的各个角落,凭借着精湛的医术拯...
美股涨了,金价夺回3400美元... 2025.06.03本文字数:1091,阅读时长大约1分钟作者 |第一财经 樊志菁周一,美股低开高走...
大额存单利率全面降至“1字头”... 说起最近的各种理财,相信很多人都会感叹这个利率水平实在是太低了,就在最近大额存单利率全面降至“1字头...
“银发族”拯救KTV? “银发... 斑马消费 陈碧婷前段时间,一张有关“中国人主流娱乐方式在三年前和目前参与人数”的调研截图广为流传并引...
AGI的不归之途 AGI,即通用人工智能,正踏上一条不归之途。它犹如一艘在未知海域航行的巨轮,不断探索着智慧的边界。一...
欧盟起草对俄第18轮制裁措施 ... 来源:新华网新华社布鲁塞尔6月2日电(记者张兆卿)欧盟委员会2日发表声明说,欧盟正制定针对俄罗斯的第...
原创 心... 在现代商业环境中,烘焙行业作为食品产业的一个重要分支,正快速发展,面包作为其核心产品,备受瞩目。如今...