JSON应用非常广泛,对于Java常用的JSON库要完全掌握。@pdai
一个简单实例
{
"Image": {
"Width": 800,
"Height": 600,
"Title": "View from 15th Floor",
"Thumbnail": {
"Url": "http://www.example.com/image/481989943",
"Height": 125,
"Width": "100"
},
"IDs": [116, 943, 234, 38793]
}
}
Java中并没有内置JSON的解析,因此使用JSON需要借助第三方类库。
下面是几个常用的 JSON 解析类库:
从下面的测试结果可以看出,序列化次数比较小的时候,Gson性能最好,当不断增加的时候到了100000,Gson明细弱于Jackson和FastJson, 这时候FastJson性能是真的牛,另外还可以看到不管数量少还是多,Jackson一直表现优异。而那个Json-lib可以直接忽略。
更多请参考: Java几种常用JSON库性能比较
Fastjson 是一个 Java 库,可以将 Java 对象转换为 JSON 格式,当然它也可以将 JSON 字符串转换为 Java 对象。
Fastjson 可以操作任何 Java 对象,即使是一些预先存在的没有源码的对象。
你可以在 maven 中央仓库中直接下载:http://repo1.maven.org/maven2/com/alibaba/fastjson/
配置 maven 依赖:
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>x.x.xversion>
dependency>
其中 x.x.x 是版本号,根据需要使用特定版本,建议使用最新版本。
User user = new User();
user.setName("校长");
user.setAge(3);
user.setSalary(new BigDecimal("123456789.0123"));
String jsonString = JSON.toJSONString(user);
System.out.println(jsonString);
// 输出 {"age":3,"name":"校长","old":false,"salary":123456789.0123}
String jsonString = "{\"age\":3,\"birthdate\":1496738822842,\"name\":\"校长\",\"old\":true,\"salary\":123456789.0123}";
User u = JSON.parseObject(jsonString ,User.class);
System.out.println(u.getName());
// 输出 校长
String jsonStringArray = "[{\"age\":3,\"birthdate\":1496738822842,\"name\":\"校长\",\"old\":true,\"salary\":123456789.0123}]";
List<User> userList = JSON.parseArray(jsonStringArray, User.class);
System.out.println(userList.size());
// 输出 1
默认序列化Date输出使用”yyyy-MM-dd HH:mm:ss”格式,可以用UseISO8601DateFormat特性换成”yyyy-MM-dd’T’HH:mm:ss”格式。
JSON.defaultTimeZone = TimeZone.getTimeZone("Asia/Shanghai");
JSON.defaultLocale = Locale.US;
public static class Model {
@JSONField(format = "MMM dd, yyyy h:mm:ss aa")
private java.util.Date date;
public java.util.Date getDate() {
return date;
}
public void setDate(java.util.Date date) {
this.date = date;
}
@JSONField(format = "MMM-dd-yyyy h:mm:ss aa")
public java.sql.Date date2;
}
public class A {
@JSONField(name="ID")
private int id;
public int getId() {return id;}
public void setId(int value) {this.id = id;}
}
public class A {
@JSONField(serialize=false)
public Date date;
}
public class A {
@JSONField(deserialize=false)
public Date date;
}
public static class VO {
@JSONField(ordinal = 3)
private int f0;
@JSONField(ordinal = 2)
private int f1;
@JSONField(ordinal = 1)
private int f2;
}
尽量使用最新版本。
这些扩展是插件式的Jackson模块,用ObjectMapper.registerModule()注册,并且通过添加serializers和deserializers以便Databind包(ObjectMapper / ObjectReader / ObjectWriter)可以读写这些类型,来增加对各种常用的Java库的数据类型的支持。
Jackson也有处理程序对JAX-RS标准实现者例如Jersey, RESTeasy, CXF等提供了数据格式支持。处理程序实现了MessageBodyReader和MessageBodyWriter,目前支持的数据格式包括JSON, Smile, XML, YAML和CBOR。
数据格式提供了除了Json之外的数据格式支持,它们绝大部分仅仅实现了streaming API abstractions,以便数据绑定组件可以按照原来的方式使用。另一些(几乎不需要)提供了databind标准功能来处理例如schemas。
引用maven jar包:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.10.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.1</version>
</dependency>
public void toJson() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
City case1 = new City();
case1.setCity("SZ");
case1.setAge(123);
String jsonStr = mapper.writeValueAsString(case1);
System.out.println("JSON:" + jsonStr);
}
// 输出:JSON:{"city":"SZ","age":123}
public void toObj() throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
String inputjsonstr = "{\"city\":\"SZ\",\"age\":123}";
City readcase = mapper.readValue(inputjsonstr, City.class);
System.out.println("city info:" + readcase);
}
如果里面有未知属性,比如json中有
desc
字段,但是City中没有相应字段,会报错, 需要设置如下:
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
@JsonProperty("xxx")
: 将当前的属性名在json字符串中重新命名为当前设置的这个值,比如在示例中,将age–>mAge@JsonIgnore
: 将被标注的属性在生成json字符串的时候,直接忽略@JsonInclude
: 是一个类级别的设置,JsonInclude.Include.NON_EMPTY标识只有非NULL的值才会被纳入json string之中,其余的都被忽略,比如这里的location属性,并没有出现在最终的结果字符串中。@JsonSerialize
: 使用自定义的类来实现自定义的字段转换。写入操作。@JsonDeserialize
: 解析的时候,自定义的转换器;读取操作。@JsonAutoDetect
: 设置类的访问策略,是否所有的属性都可以,还是按照一定的方式来提取。@JsonRawValue
: 无转换的将属性值写入到json 字符串中。 写入操作@JsonValue
: 标注方法,用以替代缺省的方法,由该方法来完成json的字符输出。Gson是这样一个Java类库,它可以将Java对象转换为相应的JSON形式,也可以将JSON字符串转换为对应的Java对象。
Gson可以使用任意Java对象,包括哪些预先存在的、不在你的源代码中的对象(因此,你并不知道对象的属性)。
使用Gson的首要类是Gson类,你可以仅仅通过new Gson()的方式创建它。你也可以通过GsonBuilder类去创建Gson实例,这个类允许你进行一系列配置,例如版本控制等等。
Gson实例不会保存任何进行Json操作时的状态。因此,你可以自由的服用相同的Gson对象进行诸多的Json序列化和反序列化操作。
引用maven jar包:
<dependency>
<groupId>com.google.guavagroupId>
<artifactId>guavaartifactId>
<version>28.2-jreversion>
dependency>
// 基础类型
Gson gson = new Gson();
gson.toJson(1); ==> prints 1
gson.toJson("abcd"); ==> prints "abcd"
gson.toJson(new Long(10)); ==> prints 10
int[] values = { 1 };
gson.toJson(values); ==> prints [1]
// 对象
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
==> json is {"value1":1,"value2":"abc"}
// 数组
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"abc", "def", "ghi"};
gson.toJson(ints); ==> prints [1,2,3,4,5]
gson.toJson(strings); ==> prints ["abc", "def", "ghi"]
// 集合
Gson gson = new Gson();
Collection<Integer> ints = Lists.immutableList(1,2,3,4,5);
String json = gson.toJson(ints); ==> json is [1,2,3,4,5]
其中的对象代码:
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
// 基础类型
Gson gson = new Gson();
int one = gson.fromJson("1", int.class);
Integer one = gson.fromJson("1", Integer.class);
Long one = gson.fromJson("1", Long.class);
Boolean false = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"abc\"", String.class);
String anotherStr = gson.fromJson("[\"abc\"]", String.class);
// 对象
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
==> obj2 is just like obj
// 数组
Gson gson = new Gson();
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
==> ints2 will be same as ints
// 集合
Gson gson = new Gson();
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
Collection<Integer> ints2 = gson.fromJson(json, collectionType);
ints2 is same as ints
有时候,默认的实现并不是你想要的。这在处理类库时常常发生(例如DateTime)。Gson允许你注册自己自定义的序列化器和反序列化器。该过程分为两部分:
Json序列化器:需要为一个对象自定义序列化机制。
Json反序列化器:需要为一个类型自定义反序列化机制。
实例构造者:并不需要,如果无参构造器是可用的或者注册了一个反序列化器。
GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(MyType2.class, new MyTypeAdapter());
gson.registerTypeAdapter(MyType.class, new MySerializer());
gson.registerTypeAdapter(MyType.class, new MyDeserializer());
gson.registerTypeAdapter(MyType.class, new MyInstanceCreator());
registerTypeAdapter会检查类型适配器是否实现了上面三个接口中的一个以上并且它们都注册了类型适配器。
更多请参考:Gson用户指南(中文翻译)
最全的Java后端知识体系 https://www.pdai.tech, 每天更新中…。