Java 中并没有内置 JSON 的解析,因此使用JSON需要借助第三方类库。
下面是几个常用的 JSON 解析类库:
Fastjson 简介 Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。
Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象。
Fastjson 源码地址:https://github.com/alibaba/fastjson
Fastjson 中文 Wiki:https://github.com/alibaba/fastjson/wiki/Quick-Start-CN
Fastjson 特性
提供服务器端、安卓客户端两种解析工具,性能表现较好。
提供了 toJSONString() 和 parseObject() 方法来将 Java 对象与 JSON 相互转换。调用toJSONString方 法即可将对象转换 JSON 字符串,parseObject 方法则反过来将 JSON 字符串转换成对象。
允许转换预先存在的无法修改的对象(只有class、无源代码)。
Java泛型的广泛支持。
允许对象的自定义表示、允许自定义序列化类。
支持任意复杂对象(具有深厚的继承层次和广泛使用的泛型类型)。
下载和使用 你可以在 maven 中央仓库中直接下载:
1 https://repo1.maven.org/maven2/com/alibaba/fastjson/
或者配置 maven 依赖:
1 2 3 4 5 <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>x.x.x</version> </dependency>
其中 x.x.x 是版本号,根据需要使用特定版本,建议使用最新版本。
变量编码与解码 编码 从 Java 变量到 JSON 格式的编码过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public void testJson ( ) { JSONObject object = new JSONObject(); object .put("string" ,"string" ); object .put("int" ,2 ); object .put("boolean" ,true ); List<Integer> integers = Arrays.asList(1 ,2 ,3 ); object .put("list" ,integers); object .put("null" ,null ); System.out .println(object ); }
在上例中,首先建立一个 JSON 对象,然后依次添加字符串、整数、布尔值以及数组,最后将其打印为字符串。输出结果如下:
1 {"boolean" :true ,"string" :"string" ,"list" :[1 ,2 ,3 ],"int" :2 }
解码 从 JSON 对象到 Java 变量的解码过程如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public void testJson2() { JSONObject object = JSONObject.parseObject("{\"boolean \":true,\"string\":\"string\",\"list\":[1,2,3],\"int \":2}"); //string String s = object .getString("string"); System .out .println(s); //int int i = object .getIntValue("int"); System .out .println(i); //boolean boolean b = object .getBooleanValue("boolean"); System .out .println(b); //list List<Integer > integers = JSON .parseArray(object .getJSONArray("list").toJSONString(),Integer .class ); integers.forEach (System .out ::println); //null System .out .println(object .getString("null")); }
在上例中,首先从 JSON 格式的字符串中构造一个 JSON 对象,之后依次读取字符串、整数、布尔值以及数组,最后分别打印,打印结果如下:
1 2 3 4 5 6 7 string 2 true 1 2 3 null
JSON 对象与字符串的相互转化
方法
作用
JSON.parseObject()
从字符串解析 JSON 对象
JSON.parseArray()
从字符串解析 JSON 数组
JSON.toJSONString(obj/array)
将 JSON 对象或 JSON 数组转化为字符串
实例 1 2 3 4 5 6 7 8 JSONObject obj = JSON . parseObject("{\"runoob\":\"菜鸟教程\"}" ) ; JSONArray arr = JSON . parseArray("[\"菜鸟教程\",\"RUNOOB\"]\n" ) ; String objStr = JSON .to JSONString(obj ) ; String arrStr = JSON .to JSONString(arr ) ;
Java 对象转换为 JSON 格式 (编码) 定义以下 Person JavaBean:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class Person { @JSONField(name = "AGE" ) private int age; @JSONField(name = "FULL NAME" ) private String fullName; @JSONField(name = "DATE OF BIRTH" ) private Date dateOfBirth; public Person(int age, String fullName, Date dateOfBirth) { super (); this .age = age; this .fullName= fullName; this .dateOfBirth = dateOfBirth; } }
可以使用 JSON.toJSONString() 将 Java 对象转换换为 JSON 对象:
1 2 3 4 5 6 7 8 9 10 11 12 private List<Person> listOfPersons = new ArrayList<Person>() ; @Before public void setUp() { listOfPersons.add(new Person(15, "John Doe" , new Date() )); listOfPersons.add(new Person(20, "Janette Doe" , new Date() )); } @Test public void when JavaList_thanConvertToJsonCorrect() { String jsonOutput = JSON .to JSONString(listOfPersons ) ; }
输出结果为:
1 2 3 4 5 6 7 8 9 10 11 12 [ { "AGE" :15 , "DATE OF BIRTH" :1468962431394 , "FULL NAME" :"John Doe" }, { "AGE" :20 , "DATE OF BIRTH" :1468962431394 , "FULL NAME" :"Janette Doe" } ]
@JSONField 注解 @JSONField 注解,实现自定义转换:
format 参数用于格式化 date 属性。
默认情况下, FastJson 库可以序列化 Java bean 实体, 但我们可以使用 serialize 指定字段不序列化。
使用 ordinal 参数指定字段的顺序
我们还可以自定义输出,并控制字段的排序,日期显示格式,序列化标记等。
接下来我们更新 bean 并添加几个字段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public class Person { @JSONField(name ="AGE" , serialize =false ) private int age; @JSONField(name ="LAST NAME" , ordinal = 2) private String lastName; @JSONField(name ="FIRST NAME" , ordinal = 1) private String firstName; @JSONField(name ="DATE OF BIRTH" , format ="dd/MM/yyyy" , ordinal = 3) private Date dateOfBirth; }
输出结果为:
1 2 3 4 5 6 7 8 9 10 11 12 [ { "FIRST NAME" :"Doe" , "LAST NAME" :"Jhon" , "DATE OF BIRTH" :"19/07/2016" }, { "FIRST NAME" :"Doe" , "LAST NAME" :"Janette" , "DATE OF BIRTH" :"19/07/2016" } ]
@JSONField 的作用对象:
Field
Setter 和 Getter 方法
注意: FastJson 在进行操作时,是根据 getter 和 setter 的方法进行的,并不是依据 Field 进行。
注意: 若属性是私有的,必须有 set 方法。否则无法反序列化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.alibaba.fastjson.annotation; public @interface JSONField { int ordinal () default 0 ; String name () default "" ; String format () default "" ; boolean serialize () default true ; boolean deserialize () default true ; }
JSONField 配置方式
FieldInfo 可以配置在 getter/setter 方法或者字段上。例如:
配置在 getter/setter 上
1 2 3 4 5 6 7 8 public class A { private int id; @JSONField (name="ID" ) public int getId () {return id;} @JSONField (name="ID" ) public void setId (int value) {this .id = id;} }
配置在 field 上
1 2 3 4 5 6 7 public class A { @JSONField(name="ID" ) private int id; public int getId ( ) {return id;} public void setId (int value ) {this .id = id;} }
FastJson 还支持 BeanToArray 序列化功能: 1 String jsonOutput= JSON.toJSONString(listOfPersons, SerializerFeature.BeanToArray);
输出结果为:
1 2 3 4 5 6 7 8 9 10 11 12 [ [ 15 , 1469003271063 , "John Doe" ], [ 20 , 1469003271063 , "Janette Doe" ] ]
创建 JSON 对象 创建 JSON 对象非常简单,只需使用 JSONObject(fastJson提供的json对象) 和 JSONArray(fastJson提供json数组对象) 对象即可。
我们可以把JSONObject 当成一个 Map<String,Object> 来看,只是 JSONObject 提供了更为丰富便捷的方法,方便我们对于对象属性的操作。我们看一下源码。
1 2 3 4 public class JSONObject extends JSON implements Map <String, Object >, Cloneable, Serializable , InvocationHandler { private static final long serialVersionUID = 1 L; private static final int DEFAULT_INITIAL_CAPACITY = 16 ; private final Map<String, Object> map;
同样我们可以把 JSONArray 当做一个 List,可以把 JSONArray 看成 JSONObject 对象的一个集合。
1 2 3 4 5 public class JSONArray extends JSON implements List <Object >, Cloneable, RandomAccess , Serializable { private static final long serialVersionUID = 1 L; private final List<Object> list; protected transient Object relatedArray; protected transient Type componentType;
此外,由于 JSONObject 和 JSONArray 继承了 JSON,所以说也可以直接使用两者对 JSON 格式字符串与 JSON 对象及 javaBean 之间做转换,不过为了避免混淆我们还是使用 JSON。
1 2 3 4 5 6 7 8 9 10 11 12 @Test public void whenGenerateJson\_thanGenerationCorrect() throws ParseException { JSONArray jsonArray = new JSONArray (); for (int i = 0 ; i < 2 ; i++) { JSONObject jsonObject = new JSONObject (); jsonObject.put("AGE" , 10 ); jsonObject.put("FULL NAME" , "Doe " + i); jsonObject.put("DATE OF BIRTH" , "2016/12/12 12:12:12" ); jsonArray.add (jsonObject); } String jsonOutput = jsonArray.toJSONString(); }
输出结果为:
1 2 3 4 5 6 7 8 9 10 11 12 [ { "AGE" :"10" , "DATE OF BIRTH" :"2016/12/12 12:12:12" , "FULL NAME" :"Doe 0" }, { "AGE" :"10" , "DATE OF BIRTH" :"2016/12/12 12:12:12" , "FULL NAME" :"Doe 1" } ]
JSON 字符串转换为 Java 对象 现在我们已经学会了如何创建 JSON 对象,以及如何将 Java 对象转换为 JSON 字符串,接下来我们就需要了解如何解析 JSON:
1 2 3 4 5 6 7 8 9 @Test public void when Json_thanConvertToObjectCorrect() { Person person = new Person(20, "John" , "Doe" , new Date() ); String jsonObject = JSON .to JSONString(person ) ; Person newPerson = JSON . parseObject(jsonObject , Person.class ) ; assert Equals(newPerson .getAge () , 0 ); assert Equals(newPerson .getFullName () , listOfPersons.get(0 ).getFullName() ); }
我们可以使用 JSON.parseObject() 将 JSON 字符串转换为 Java 对象。
注意反序列化时为对象时,必须要有默认无参的构造函数,否则会报异常:
1 com.alibaba.fastjson.JSONException: default constructor not found.
以下是简单的实例测试:
1 Person [age=20, fullName=John Doe, dateOfBirth=Wed Jul 20 08:51:12 WEST 2016]
@JSONField deserialize 可选项可以指定字段不反序列化。
1 2 @JSONField(name = "DATE OF BIRTH", deserialize=false) private Date dateOfBirth;
输出结果为:
1 Person [age=20, fullName=John Doe, dateOfBirth=null]
使用 ContextValueFilter 配置 JSON 转换 在某些场景下,对Value做过滤,需要获得所属JavaBean的信息,包括类型、字段、方法等。在fastjson-1.2.9中,提供了ContextValueFilter,类似于之前版本提供的ValueFilter,只是多了BeanContext参数可用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @Test public void givenContextFilter_whenJavaObject_thanJsonCorrect() { ContextValueFilter valueFilter = new ContextValueFilter () { public Object process( BeanContext context, Object object , String name , Object value ) { if (name .equals("DATE OF BIRTH")) { return "NOT TO DISCLOSE"; } if (value .equals("John")) { return ((String) value ).toUpperCase(); } else { return null ; } } }; String jsonOutput = JSON .toJSONString(listOfPersons, valueFilter); }
以上实例中我们隐藏了 DATE OF BIRTH 字段,并过滤名字不包含 John 的字段:
1 2 3 4 5 6 [ { "FULL NAME":"JOHN DOE", "DATE OF BIRTH":"NOT TO DISCLOSE" } ]
使用 NameFilter 和 SerializeConfig NameFilter : 序列化时修改 Key。
SerializeConfig :内部是个map容器主要功能是配置并记录每种Java类型对应的序列化类。
1 2 3 4 5 6 7 8 9 10 11 @Test public void givenSerializeConfig_whenJavaObject_thanJsonCorrect() { NameFilter formatName = new NameFilter() { public String process(Object object, String name, Object value) { return name.to LowerCase() .replace(" " , "_" ); } }; SerializeConfig . getGlobalInstance() .addFilter(Person.class , formatName ) ; String jsonOutput = JSON .to JSONStringWithDateFormat(listOfPersons , "yyyy-MM-dd" ) ; }
实例中我们声明了 formatName 过滤器使用 NameFilter 匿名类来处理字段名称。 新创建的过滤器与 Person 类相关联,然后添加到全局实例,它是 SerializeConfig 类中的静态属性。
现在我们可以轻松地将对象转换为JSON格式。
注意我们使用的是 toJSONStringWithDateFormat() 而不是 toJSONString() ,它可以更快速的格式化日期。
输出结果:
1 2 3 4 5 6 7 8 9 10 [ { "full_name":"John Doe", "date_of_birth":"2016-07-21" }, { "full_name":"Janette Doe", "date_of_birth":"2016-07-21" } ]