Android:尝试序列化...忘记注册类型适配器?"

Ily*_*man 9 android json gson

如何使用Gson将HashMap转换为JSON .

class ClassData {
    public String jsonString;
    public Class classType;
}
HashMap<String, ClassData> map = new HashMap<>();

void convert(){
    new Gson().toJson(map); // throws
}
Run Code Online (Sandbox Code Playgroud)

我得到了下一个例外

尝试序列化java.lang.Class:java.lang.String.忘了注册一个类型适配器?

小智 10

我的方法适用于带有Java 1.7的Gson 2.3.1,不能保证它适用于Android.

问题在于变量classType,因为Gson无法按Class原样处理类型.所以我们必须为Class创建一个TypeAdapter.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

为了使它工作,你需要一个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();
    }
}
Run Code Online (Sandbox Code Playgroud)

并将TypeAdapterFactory注册到您的Gson Builder.

gsonBuilder.registerTypeAdapterFactory(new ClassTypeAdapterFactory());
Run Code Online (Sandbox Code Playgroud)

AFAIK你必须使用TypeAdapterFactory.直接注册的TypeAdapter

gsonBuilder.registerTypeAdapter(Class.class, new ClassTypeAdapter());
Run Code Online (Sandbox Code Playgroud)

Class遇到类型的对象时似乎被忽略.

Gson将HashMapJava类实例和Java类实例转换为JSON对象.例:

{
    "hash_key_1": {
        "jsonString": "json_string_instance_1",
        "classType": "my.class.Name1"
    },
    "hash_key_2": {
        "jsonString": "json_string_instance_2",
        "classType": "my.class.Name2"
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 4

您需要为 ClassData 实现您自己的自定义序列化器,然后将其注册到您的 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:{“键”:“键”}

了解更多:https ://sites.google.com/site/gson/gson-user-guide#TOC-Writing-a-Serializer