在将 json 字符串转为对象时,如果对象含有泛型,在进行转换时需要指明泛型类型。
1. 对象只含有一个泛型属性时
1.1 代码
/** * @Describe: * @Author: chenfan * @Date: 2019/5/9 19:15 */ @Data /** * 含有泛型属性的对象 */ class OneGeneric<E>{ E e; String ss; } @Data /** * 泛型对象 */ class KeyMessage{ String kk; } public class JsonTest { public static void main(String[] args) { // {"e": {"kk":"qwe"},"ss": "ssValue"} String data = "{"e": {"kk":"qwe"},"ss": "ssValue"}"; Gson gson = new Gson(); // OneGeneric : 外层对象类型 KeyMessage :嵌套的泛型类型 OneGeneric one = gson.fromJson(data, new TypeToken<OneGeneric<KeyMessage>>() {}.getType()); System.out.println(one); } }
1.2 运行结果
正确转换如下:
1.3 泛型属性为集合类型时
此时和只有一个泛型对象时处理方式一样
public class JsonTest { public static void main(String[] args) { // {"ss": "ssValue","list":[{"dd":"dd1"},{"dd":"dd2"}]} String data = "{"ss": "ssValue","list":[{"dd":"dd1"},{"dd":"dd2"}]}"; Gson gson = new Gson(); OneGeneric grandMessage = gson.fromJson(data, new TypeToken<OneGeneric<Generic>>() {}.getType()); System.out.println(grandMessage); } } /** * 含有泛型属性的对象 */ @Data class OneGeneric<E>{ List<E> list; String ss; } @Data class Generic{ String dd; }
2. 对象只含有多个泛型属性时
2.1 代码
/** * @Describe: * @Author: chenfan * @Date: 2019/5/9 19:15 */ @Data /** * 含有多个泛型属性的对象 */ class GrandMessage<K,V>{ K key; V value; } /** * 泛型对象 */ @Data class KeyMessage{ String kk; } /** * 泛型对象 */ @Data class ValueMessage{ String vv; } /** * 测试类 */ public class JsonTest { public static void main(String[] args) { // {"key": {"kk":"qwe"},"value": {"vv":"asd"}} String data = "{"key": {"kk":"qwe"},"value": {"vv":"asd"}}"; Gson gson = new Gson(); GrandMessage grandMessage = gson.fromJson(data, new TypeToken<GrandMessage<KeyMessage,ValueMessage>>() {}.getType()); System.out.println(grandMessage); } }
2.2 运行结果
2.3 泛型的顺序问题
在进行对象转换时, TypeToken<GrandMessage<KeyMessage,ValueMessage>> 中的泛型类型顺序必须按照 GrandMessage<K,V> 中声明的顺序,否则会对象属性全部为null
3. 泛型类型嵌套
3.1 代码
@Data class GrandMessage<K>{ K k; String msg; } @Data class OneGeneric<E>{ E e; String one; } @Data class Generic{ String dd; } /** * 测试类 */ public class JsonTest { public static void main(String[] args) { // {"msg":"lili","k":{"one":"111","e":{"dd":"dddd"}}} String data = "{"msg":"lili","k":{"one":"111","e":{"dd":"dddd"}}}"; Gson gson = new Gson(); // 转换时的泛型顺序一定要严格按照对象的嵌套顺序 GrandMessage grandMessage = gson.fromJson(data, new TypeToken<GrandMessage<OneGeneric<Generic>>>() {}.getType()); System.out.println(grandMessage); } }
3.2 运行结果
4. 自定义转换逻辑
JSON转对象时,如果对象某个属性不确定(比如对象定义为Object,实际为 int 类型),需要自定义转换逻辑
显示指定 OpSessionControlMessage 的 messageId 为 int 类型:
private static Gson gson2 = new GsonBuilder() .registerTypeAdapter( new TypeToken<OpSessionControlMessage>(){}.getType(), new JsonDeserializer<OpSessionControlMessage>() { @Override public OpSessionControlMessage deserialize( JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { OpSessionControlMessage message = new OpSessionControlMessage(); JsonObject jsonObject = json.getAsJsonObject(); Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet(); for (Map.Entry<String, JsonElement> entry : entrySet) { Object ot = entry.getValue(); if(entry.getKey().equals("messageId")){ message.setOpType(((JsonPrimitive) ot).getAsInt()); } } return message; } }).create();