Android: Attempted to serialize … Forgot to register a type adapter?\"

匿名 (未验证) 提交于 2019-12-03 01:33:01

问题:

How to convert HashMap to JSON using Gson.

class ClassData {     public String jsonString;     public Class classType; } HashMap<String, ClassData> map = new HashMap<>();  void convert(){     new Gson().toJson(map); // throws } 

I am getting the next exception

Attempted to serialize java.lang.Class: java.lang.String. Forgot to register a type adapter?

回答1:

You need to implement your own custom serializer for ClassData, and then register it to your Gson Builder.

public class ClassDataSerializerExample {     static class ClassData {         public String jsonString;         public Class classType;          public ClassData(String jsonString, Class classType) {             this.jsonString = jsonString;             this.classType = classType;         }     }      static class ClassDataSerializer implements JsonSerializer<ClassData> {         @Override         public JsonElement serialize(ClassData src, Type typeOfSrc, JsonSerializationContext context) {             return new JsonPrimitive(src.jsonString);         }     }      public static void main(String[] args) {         GsonBuilder gsonBuilder = new GsonBuilder();         gsonBuilder.registerTypeAdapter(ClassData.class, new ClassDataSerializer());          HashMap<String, ClassData> map = new HashMap<>();         map.put("key", new ClassData("key", String.class));          Gson gson = gsonBuilder.create();         String json = gson.toJson(map);          System.out.println(json);     } } 

Output: {"key":"key"}

Read more: https://sites.google.com/site/gson/gson-user-guide#TOC-Writing-a-Serializer



回答2:

My approach works for Gson 2.3.1 with Java 1.7, can't guarantee it will work with Android.

The problem lies within the variable classType, since Gson can't process the type Class as it is. So we have to create a TypeAdapter for Class.

public class ClassTypeAdapter extends TypeAdapter<Class<?>> {     @Override     public void write(JsonWriter jsonWriter, Class<?> clazz) throws IOException {         if(clazz == null){             jsonWriter.nullValue();             return;         }         jsonWriter.value(clazz.getName());     }      @Override     public Class<?> read(JsonReader jsonReader) throws IOException {         if (jsonReader.peek() == JsonToken.NULL) {             jsonReader.nextNull();             return null;         }         Class<?> clazz = null;         try {             clazz = Class.forName(jsonReader.nextString());         } catch (ClassNotFoundException exception) {             throw new IOException(exception);         }         return clazz;     } } 

To make it work you'll need a TypeAdapterFactory.

public class ClassTypeAdapterFactory implements TypeAdapterFactory {     @Override     public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {         if(!Class.class.isAssignableFrom(typeToken.getRawType())) {             return null;         }         return (TypeAdapter<T>) new ClassTypeAdapter();     } } 

And register the TypeAdapterFactory to your Gson Builder.

gsonBuilder.registerTypeAdapterFactory(new ClassTypeAdapterFactory()); 

AFAIK you have to use a TypeAdapterFactory. A directly registered TypeAdapter

gsonBuilder.registerTypeAdapter(Class.class, new ClassTypeAdapter()); 

seems to be ignored when an object of type Class is encountered.

Gson transforms both the HashMap and Java class instances to JSON objects. Example:

{     "hash_key_1": {         "jsonString": "json_string_instance_1",         "classType": "my.class.Name1"     },     "hash_key_2": {         "jsonString": "json_string_instance_2",         "classType": "my.class.Name2"     } } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!