google / google/gson

Allow TypeAdapters for Object

Open
#1,177 4 comments 3 reactions 0 assignees View on GitHub
enhancement
Dominant language
Java
Stars
24.2k
Forks
4.5k
Avg merge
6d 4h
Merged PRs (30d)
12

Description

Hi,
I have the classes

- A
- AB -> A
- C

I want to serialize/deserialize a list of them using the RuntimeTypeAdapterFactory (from extras), which works fine if I only use A and AB.

System.out.println("Test Base A");
System.out.println("##############");
System.out.println("--------------");

List list = new ArrayList<>();
list.add(new A("aa"));
list.add(new AB("aaa", "bbb"));

Type type = new TypeToken>()
{
}.getType();

System.out.println(list);
System.out.println("--------------");

RuntimeTypeAdapterFactory runtimeTypeApatper = RuntimeTypeAdapterFactory.of(A.class);
runtimeTypeApatper.registerSubtype(A.class);
runtimeTypeApatper.registerSubtype(AB.class);

Gson gson = new GsonBuilder().registerTypeAdapterFactory(runtimeTypeApatper)
.setPrettyPrinting()
.create();

String json = gson.toJson(list, type);

System.out.println(json);
System.out.println("--------------");

List list2 = gson.fromJson(json, type);

System.out.println(list2);
System.out.println("--------------");
System.out.println(list.equals(list2));

But to add also C to the list, I need a RuntimeTypeAdapterFactory of the Object class, see:

System.out.println("Test Base Object");
System.out.println("##############");
System.out.println("--------------");

List list = new ArrayList<>();
list.add(new A("aa"));
list.add(new AB("aaa", "bbb"));
list.add(new C("cc", new D("dd")));

Type type = new TypeToken>()
{
}.getType();

System.out.println(list);
System.out.println("--------------");

RuntimeTypeAdapterFactory runtimeTypeApatper = RuntimeTypeAdapterFactory
.of(Object.class);
runtimeTypeApatper.registerSubtype(A.class);
runtimeTypeApatper.registerSubtype(AB.class);
runtimeTypeApatper.registerSubtype(C.class);

Gson gson = new GsonBuilder().registerTypeAdapterFactory(runtimeTypeApatper)
.setPrettyPrinting()
.create();

String json = gson.toJson(list, type);

System.out.println(json);
System.out.println("--------------");

List list2 = gson.fromJson(json, type);

System.out.println(list2);
System.out.println("--------------");
System.out.println(list.equals(list2));

But this does not work. I looked at your code and found the problem in com.google.gson.Gson.Gson(…)

List factories = new ArrayList();

// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
factories.add(ObjectTypeAdapter.FACTORY);

// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);

// users' type adapters
factories.addAll(factoriesToBeAdded);

// type adapters for basic platform types
factories.add(TypeAdapters.STRING_FACTORY);
...

I we reorder the lines, so that the ObjectTypeAdapter is added after the user defined factories, my example works!

List factories = new ArrayList();

// built-in type adapters that cannot be overridden
factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
// the excluder must precede all adapters that handle user-defined types
factories.add(excluder);

// users' type adapters
factories.addAll(factoriesToBeAdded);

factories.add(ObjectTypeAdapter.FACTORY);

// type adapters for basic platform types
factories.add(TypeAdapters.STRING_FACTORY);

(Code is attached)
[test.zip](https://github.com/google/gson/files/1409787/test.zip)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.