Gson对枚举的处理

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:roll_eyes:

1 Like