原文地址:https://www.jianshu.com/p/e740196225a4
简介:
JSON 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成
Java中最常用的类库有:JSON-Java、Gson、Jackson、FastJson等
注意点
1.一个对象以 {
左括号 开始,}
右括号 结束
2.一个数组以[
左中括号 开始,]
右中括号 结束
3.字符串是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义引号。
集成Gson
com.google.code.gson
gson
2.8.5
一、Gson的基本用法
Gson提供了fromJson()
和toJson()
两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。同时每个方法都提供了重载方法,我常用的总共有5个。
下文学习
Gson.toJson(Object);
Gson.fromJson(Reader,Class);
Gson.fromJson(String,Class);
Gson.fromJson(Reader,Type);
Gson.fromJson(String,Type);
基本数据类型的解析
Gson gson = new Gson();
int i = gson.fromJson("100", int.class); //100
double d = gson.fromJson("\"99.99\"", double.class); //99.99
boolean b = gson.fromJson("true", boolean.class); // true
String str = gson.fromJson("String", String.class); // String
第二行为一个字符串
基本数据类型的生成
Gson gson = new Gson();
String jsonNumber = gson.toJson(100); // 100
String jsonBoolean = gson.toJson(false); // false
String jsonString = gson.toJson("String"); //"String"
普通java对象的生成与解析
public class Student {
public String name;
public int age;
public String emailAddress;
//省略其他
public Student(String name, int age, String emailAddress) {
this.name = name;
this.age = age;
this.emailAddress = emailAddress;
}
public Student() {
}
}
Gson gson = new Gson();
Student student = new Student("星星",22,"[email protected]");
String jsonObject = gson.toJson(student);
System.out.println(jsonObject);
//{"name":"星星","age":22,"emailAddress":"[email protected]"}
二、属性重命名 @SerializedName 注解的使用
默认的json的字段和值是和类中名称和类型是一一对应的
现在想实现
{"name":"星星","age":22,"emailAddress":"[email protected]"}
不想要这样的email,需求下面的样式
{"name":"星星","age":22,"email_address":"[email protected]"}
SerializedName注解的使用
1.@SerializedName("email_address")
public String emailAddress;
解释为把emailAddress变成email_address
上面的代码生成的json就是下面这样的了
{"name":"星星","age":22,"email_address":"[email protected]"}
2.@SerializedName(value = "emailAddress", alternate = {"email", "email_address"})
一个String,一个String数组表示备选属性名
解释为json生成类的时候,遇到email或者email_address都变成emailAddress
三、Gson中使用泛型
1.JSON解析字数组
一般有两种方式:使用数组,使用List。List对于增删都是比较方便的,所以实际使用是还是List比较多。
使用数组
Gson gson = new Gson();
String arraystr = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(arraystr, String[].class);
System.out.println(Arrays.toString(strings));
//[Android, Java, PHP]
但对于List将上面的代码中的
String[].class
直接改为List
是行不通的。对于Java来说.class List
和List
这俩个的字节码文件只一个那就是List.class
,这是Java泛型使用时要注意的问题 泛型擦除
为了解决的上面的问题,Gson为我们提供了TypeToken
来实现对泛型的支持,所以当我们希望使用将以上的数据解析为List
时需要这样写。
Gson gson = new Gson();
String arraystr = "[\"Android\",\"Java\",\"PHP\"]";
List stringList = gson.fromJson(arraystr, new TypeToken>() {}.getType());
System.out.println(stringList);
//[Android, Java, PHP]
TypeToken
的构造方法是protected
修饰的,所以上面才会写成
new TypeToken
>() {}.getType()
而不是
new TypeToken
>().getType()
2.当返回的数据分为两类或者更多比如:
data是数组
{"code":"0","message":"success","data":[]}
data是对象
{"code":"0","message":"success","data":{}}
现在怎么设计这个大的对象呢?
public class Result {
public int code;
public String message;
public T data;
}
这样用泛型代替
那么对于data字段是User时则可以写为 Result>,其它同理。
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.*;
public class Main {
public static void main(String[] args) {
Gson gson = new Gson();
// data是数组
String str1 = "{\"code\":\"0\",\"message\":\"success\",\"data\":[{\"name\":\"星星1\",\"age\":\"22\",\"email\":\"[email protected]\"},{\"name\":\"星星2\",\"age\":\"22\",\"email\":\"[email protected]\"}]}";
// data是对象
String str2 = "{\"code\":\"0\",\"message\":\"success\",\"data\":{\"name\":\"星星\",\"age\":\"22\",\"email\":\"[email protected]\"}}";
//data是数组
Type userListType = new TypeToken>>(){}.getType();
Result> userListResult = gson.fromJson(str1,userListType);
System.out.println(gson.toJson(userListResult));
//{"code":0,"message":"success","data":[{"name":"星星1","age":22,"email":"[email protected]"},{"name":"星星2","age":22,"email":"[email protected]"}]}
//data是对象
Type userType = new TypeToken>(){}.getType();
Result userResult = gson.fromJson(str2,userType);
System.out.println(gson.toJson(userResult));
//{"code":0,"message":"success","data":{"name":"星星","age":22,"email":"[email protected]"}}
}
}
当data数组里面里面为字符串的时候:
String str1 = "{\"code\":\"0\",\"message\":\"success\",\"data\":[\"123\",\"456\"]}";
Type userListType = new TypeToken>>(){}.getType();
Result> userListResult = gson.fromJson(str1,userListType);
System.out.println(gson.toJson(userListResult));
尝试为List 失败
四、解析如下奇葩字符串
{
0={"name":"星星1","age":22,"email":"[email protected]"},
1={"name":"星星2","age":22,"email":"[email protected]"},
2={"name":"星星3","age":22,"email":"[email protected]"}
}
这里用到自定义反序列化
利用JsonDeserializer
接口只需要实现一个反序列化方法deserialize
就足够了
1.定义解析成的类型User2
public class User2 {
Map map;
class Data {
public String name;
public int age;
public String email;
@Override
public String toString() {
return "Data{" +
"name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
'}';
}
}
}
2.定义自定义的反序列化
public class MapDeserializer implements JsonDeserializer {
// 当请求将JSON内容反序列成java类型对象的时候,该方法将会被调用。然后,会返回一个
// 由方法自己构造的对象实例。
// 需要注意的是,当JSON为null的时候,该方法该不会被调用,因此,方法不需要去check 该值是否为null
//参数1 是json字符串 参数2 是返回的类型 参数3传递给自定义反序列化器的上下文 抛出错误如果解析的json字符串不包括指定的类型
@Override
public User2 deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
// 将指定成员作为JsonObject获取的便捷方法。
JsonObject jsonObject=jsonElement.getAsJsonObject();
// 返回此对象的一组成员。
Set> set=jsonObject.entrySet();
// 定义map
Map map = new HashMap<>();
// 遍历set
for(Map.Entry s : set){
// 定义一个user2的data
User2.Data data = jsonDeserializationContext.deserialize(s.getValue().getAsJsonObject(), User2.Data.class);
// 入map s.getKey() 和 data
map.put(Integer.valueOf(s.getKey()),data);
}
// 最后返回一个整体User2
User2 user2 = new User2();
user2.map=map;
return user2;
}
}
3.注册自定义的反序列化并使用
public static void main(String[] args) {
String str = "{0={\"name\":\"星星1\",\"age\":22,\"email\":\"[email protected]\"},1={\"name\":\"星星2\",\"age\":22,\"email\":\"[email protected]\"},2={\"name\":\"星星3\",\"age\":22,\"email\":\"[email protected]\"}}";
User2 user2 = new User2();
Gson gson = new GsonBuilder()
.registerTypeAdapter(User2.class, new MapDeserializer())//为User2注册MapDeserializer
.create();
user2 = gson.fromJson(str,User2.class);
System.out.println(user2.map.get(1));
// Data{name='星星2', age=22, email='[email protected]'}
}