本文介绍Java中的Json相关类
Java的Json包
在org.json
包中
最重要的是JSONObject
和JSONArray
两个结构,对应JSON
对象和JSON
数组
JSONObject
JSONObject json = new JSONObject("{'name' : 'Alice', 'age' : 20}");
String name = json.getString("name");
int age = json.getInt("age");
从JSON
字符串获得JSONObject
,从JSON
对象中获得属性
// 一个空的对象
public JSONObject();
// 传入键值对
public JSONObject(Map copyFrom);
// 传入JSON字符串
public JSONObject(String json) throws JSONException;
// 传入一个Token
public JSONObject(JSONTokener readFrom) throws JSONException;
// 应该是从一个已有的对象里取得对应的键值对来形成一个新对象
public JSONObject(JSONObject copyFrom, String[] names) throws JSONException;
一组构造函数
JSONArray
JSONArray array = new JSONArray("[{'name' : 'Alice', 'age' : 20}, {'name' : 'Eric', 'age' : 15}]");
for (int i = 0; i < array.length(); i++){
JSONObject json = array.getJSONObject(i).
String name = json.getString("name");
int age = json.getInt("age");
}
从字符串获得JSONArray
,遍历其中的JSONObject
public JSONArray() {
public JSONArray(Collection copyFrom);
public JSONArray(String json) throws JSONException;
public JSONArray(Object array) throws JSONException;
public JSONArray(JSONTokener readFrom) throws JSONException;
也有一组不同的构造函数
可以嵌套使用,通过getJSONArray()
获得数组,遍历数组获得JSONObject
JSONStringer
用来快速构建JSON
字符串
JSONStringer stringer = new JSONStringer();
String str = stringer.object().key("name").value("Eric").key("age").value(20).endObject().toString();
JSONToken
JSONTokener
方法获得一个对象,根据括号类型或引号决定是什么(JSONObject
或JSONArray
或字符串)
// 可以从文件中读取一个JSONObject
JSONObject obj = new JSONObject( new JSONTokener(java.io.Reader));
// 可以从文件中读取一个JSONArray
JSONArray obj = new JSONArray( new JSONTokener(java.io.Reader));
JSONWriter
用来输出JSON
PrintWriter out = new PrintWriter(System.out);
new JSONWriter(out).object().key("name").value("Alice").endObject();
out.flush();
out.close();
GSON
基本用法
Gson gson = new Gson();
// 基础类型
int i = gson.fromJson("100", int.class);
double d = gson.fromJson("99.99", double.class);
boolean b = gson.fromJson("true", boolean.class);
String s = gson.fromJson("Hello", String.class);
定义一个类
public class User {
public String name;
public int id;
}
解析
Gson gson = new Gson();
User user = gson.fromJson("{'name' : 'Alice', 'id' : 1}", User.class);
生成
User user = new User;
user.name = 'Eric';
user.id = 1;
Gson gson = new Gson();
String string = gson.toJson(user);
SerializedName
后台开发经常会用到下划线命名变量,这时需要使用@SerializedName
来标记一下对应关系
{"name" : "Alice", "email_address" : "alice@example.com"}
这时的类应该是
public class User {
public String name;
@SerializedName("email_address")
public String emailAddress;
}
另外可以提供备选名
@SerializedName("email_address", alternate = {"email"})
public String emailAddress;
对象数组
Gson gson = new Gson();
String string = "['Android', 'Java', 'PHP']";
String[] langs = gson.fromJson(string, String[].class);
因为泛型擦除机制,列表不能这样用,需要使用TypeToken
List<String> langs = gson.fromJson(string, new TypeToken<List<String>>(){}.getType());
引入泛型
泛型的引入可以减少无关的代码,很多时候后台返回的结果是这样的
{"code" : "0", "message" : "success", "data" : {}}
data
中的东西可能不一样,但不需要每个都定义一个类,定义泛型类就好了
public class Result<T> {
public int code;
public String message;
public T data;
}
返回的东西是个User
就写Result<User>
,是个List<User>
就写Result<List<User>>
自定义
手动反序列化
String json = "{'name' : 'Alice', 'age' : 24}";
User user = new User();
JsonReader reader = new JsonReader(new StringReader(json));
reader.beginObject();
while (reader.hasNext()) {
String s = reader.nextName();
switch (s) {
case "name":
user.name = reader.nextString();
break;
case "age":
user.age = reader.nextInt();
break;
}
}
reader.endObject();
自动方式最后也是通过JsonReader
来实现的
手动序列化
JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));
writer.beginObject().name("name").value("Alice").name("age").value(24).endObject();
writer.flush();
GsonBuilder
可以用来自定义Gson
Gson gson = new GsonBuilder().create();
Gson
默认不输出null
值,可以用serializeNulls()
来配置
通过setDateFormat("yyyy-MM-dd")
格式化日期
disableInnerClassSerialization()
禁止序列化内部类
字段过滤
字段过滤是比较常用的技巧,在处理业务逻辑时可能需要在设置的POJO
中加入一些字段,但显然在序列化的过程中是不需要的,并且如果序列化还可能带来一个问题就是循环引用
@Expose注解
这个注解必须和GsonBuilder
结合使用,需要导出的加该注解,不需要的不加
public class Category {
@Expose
public int id;
@Expose
public String name;
@Expose
public List<Category> children;
public Category parent;
}
序列化的方法也要改
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
基于版本
使用@Since
和@Until
注解导出指定版本的字段,与setVersion()
一起使用
class SinceUntilSample {
// 版本不小于4时导出
@Since(4)
public String since;
// 版本不大于5时导出
@Until(5)
public String until;
}
Gson gson = new GsonBuilder().setVersion(version).create();
基于访问修饰符
Gson gson = new GsonBuilder().excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.PRIVATE).create();
基于策略
Gson gson = new GsonBuilder().addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
if ("finalField".equals(f.getName())) {
return true;
}
Expose expose = f.getAnnotation(Expose.class);
if (expose != null && expose.deserialize() == false) { return true;
}
return false;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return (clazz == int.class || clazz == Integer.class);
}
}).create();
终极:TypeAdapter
public abstract class TypeAdapter<T> {
public abstract void write(JsonWriter out, T value) throws IOException;
public abstract T read(JsonReader in) throws IOException;
......
}
这个类接管某种类型的序列化和反序列化
public class UserTypeAdapter extends TypeAdapter<User> {
@Override
public void write(JsonWriter out, User value) throws IOException {
out.beginObject();
out.name("name").value(value.name);
out.name("age").value(value.age);
out.endObject();
}
@Override
public User read(JsonReader in) throws IOException {
User user = new User();
in.beginObject();
while (in.hasNext()) {
switch (in.nextName()) {
case "name":
user.name = in.nextString();
break;
case "age":
user.age = in.nextInt();
break;
}
}
in.endObject();
return user;
}
}
Gson gson = new GsonBuilder().registerTypeAdapter(User.class, new UserTypeAdapter()).create();
这个类的处理优先级最高,会覆盖之前的所有注解
class JsonDeserializer<T>() {
@Override
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException;
}
class JsonSerializer<T>() {
@Override
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);
};
如果只想接管其中一个过程,则只需要实现上面的一个
Gson gson = new GsonBuilder().registerTypeAdapterFactory(new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
......
}
}).create();
对应的工厂,获取对应type
的TypeAdapter
@JsonAdapter(UserTypeAdapter.class)
public class User {
......
}
使用@JsonAdapter
注解可以省去注册的代码