Gson对枚举的处理
默认
默认情况下,Gson
把枚举实例的 name()
序列化为value
值,反序列化也是通过 name()
值
import com.google.gson.Gson;
enum Gender {
GIRL,
BOY,
UNKNOWN
}
public class GsonTest {
private Integer id;
private Gender gender;
public GsonTest(Integer id, Gender gender) {
super();
this.id = id;
this.gender = gender;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
@Override
public String toString() {
return "GsonTest [id=" + id + ", gender=" + gender + "]";
}
public static void main(String[] args) {
Gson gson = new Gson();
GsonTest gsonTest = new GsonTest(1, Gender.BOY);
// 序列化
String json = gson.toJson(gsonTest);
System.out.println(json); // {"id":1,"gender":"BOY"}
// 反序列化
gsonTest = gson.fromJson(json, GsonTest.class);
System.out.println(gsonTest); // GsonTest [id=1, gender=BOY]
}
}
使用 @SerializedName 注解修改默认的枚举值
通过在枚举实例上标识@SerializedName
注解,可以把枚举字段序列化为自定义的值
enum Gender {
@SerializedName(value = "女")
GIRL,
@SerializedName(value = "男")
BOY,
@SerializedName(value = "未知")
UNKNOWN
}
Gson gson = new Gson();
GsonTest gsonTest = new GsonTest(1, Gender.BOY);
// 序列化
String json = gson.toJson(gsonTest);
System.out.println(json); // {"id":1,"gender":"男"}
// 反序列化
gsonTest = gson.fromJson(json, GsonTest.class);
System.out.println(gsonTest); // GsonTest [id=1, gender=BOY]
通过添加Adapter完成自定义的序列化和反序列化规则
枚举类型的序列化和反序列化无非就是两种数据类型
- 字符串(枚举的
name()
属性) - 数值(枚举的
ordinal()
属性)
在反序列化的场景,需要兼容这种两种数据类型(既可以是数值,也是可以字符串,都要正确反序列化为枚举实例对象)。可以通过registerTypeHierarchyAdapter
添加自定义的反序列化处理器实现。
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.annotations.SerializedName;
enum Gender {
GIRL,
BOY,
UNKNOWN
}
public class GsonTest {
private Integer id;
private Gender gender;
public GsonTest(Integer id, Gender gender) {
super();
this.id = id;
this.gender = gender;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
@Override
public String toString() {
return "GsonTest [id=" + id + ", gender=" + gender + "]";
}
public static void main(String[] args) {
Gson gson = new GsonBuilder()
.registerTypeHierarchyAdapter(Enum.class, new JsonSerializer<Enum<?>> () {
@Override
public JsonElement serialize(Enum<?> src, Type typeOfSrc, JsonSerializationContext context) {
// 使用 ordinal 序列化成基本数据类型
return new JsonPrimitive(src.ordinal());
}
})
.registerTypeHierarchyAdapter(Enum.class, new JsonDeserializer<Enum<?>> () {
@Override
public Enum<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
// 必须是基本数据类型
if (json.isJsonPrimitive()) {
JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive();
// 反射读取所有得枚举实例
Enum<?>[] enumConstants = (Enum<?>[]) Class.forName(typeOfT.getTypeName()).getEnumConstants();
if (jsonPrimitive.isNumber()) { // 数字
return enumConstants[jsonPrimitive.getAsInt()];
} else if (jsonPrimitive.isString()) { // 字符串
String val = jsonPrimitive.getAsString();
for (Enum<?> constant : enumConstants) {
if (constant.name().equalsIgnoreCase(val)) {
return constant;
}
}
}
}
} catch (ClassNotFoundException | ArrayIndexOutOfBoundsException e) {
}
throw new IllegalArgumentException("bad param:" + json.getAsString());
}
})
.create();
GsonTest test = new GsonTest(1, Gender.GIRL);
String json = gson.toJson(test);
System.out.println(json); // {"id":1,"gender":0}
test = gson.fromJson(json, GsonTest.class);
System.out.println(test); // GsonTest [id=1, gender=GIRL]
}
}
完
逐渐放弃Fastjson
,拥抱Gson
。