Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RuntimeTypeAdapterFactory<Base> with JsonDeserializer<Derived> is unsupported #1570

Open
dbirkman-paloalto opened this issue Aug 27, 2019 · 4 comments
Labels

Comments

@dbirkman-paloalto
Copy link

Hi,

I want the RuntimeTypeAdapterFactory to differentiate between the derived class types and then deserialize the derived instance using a JsonDeserializer.
However, if I register RuntimeTypeAdapterFactory and JsonDeserializer, Gson does not serialize the derived class using the RuntimeTypeAdapterFactory.

Minimal not working example:

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.paloaltonetworks.mag.dms.utils.gson.RuntimeTypeAdapterFactory;

import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;

class Base {}
class Derived1 extends Base {}
class Derived2 extends Base {}


class Derived1Deserializer implements JsonDeserializer<Derived1> {
    @Override
    public Derived1 deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        System.out.println("Can customize deserializing Derived1");
        return null;
    }
}

public class Test {
    private List<Base> bases;

    public static void main(String[] args) {
        RuntimeTypeAdapterFactory<Base> baseRuntimeTypeAdapterFactory = RuntimeTypeAdapterFactory.of(Base.class)
                .registerSubtype(Derived1.class)
                .registerSubtype(Derived2.class);

        GsonBuilder gsonBuilder = new GsonBuilder();
        final Gson gson = gsonBuilder
                .registerTypeAdapter(Derived1.class, new Derived1Deserializer())
                .registerTypeAdapterFactory(baseRuntimeTypeAdapterFactory)
                .create();

        Test test = new Test();
        test.bases = Arrays.asList(new Derived1(), new Derived2());

        String json = gson.toJson(test);
        System.out.println(json); 
        gson.fromJson(json, Test.class);
    }
}

The toJson returns
{"bases":[{},{"type":"Derived2"}]}
instead of:
{"bases":[{"type":"Derived1"},{"type":"Derived2"}]}

and of course fromJson fails afterwards with "JsonParseException: cannot deserialize class Base because it does not define a field named type".

TIA,
Dror

@dbirkman-paloalto dbirkman-paloalto changed the title RuntimeTypeAdapterFactory<Base> and JsonDeserializer<Derived> is unsupported RuntimeTypeAdapterFactory<Base> with JsonDeserializer<Derived> is unsupported Aug 27, 2019
@tlf30
Copy link

tlf30 commented Mar 12, 2020

I am seeing the same issue, does anyone know a solution?

@dbirkman-paloalto
Copy link
Author

I didn't find any solution except for making my own copy of RuntimeTypeAdapterFactory.java and patching the code like this:

public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
    if (type.getRawType() != baseType
            // Workaround for https://github.com/google/gson/issues/1570 - START
            && !labelToSubtype.values().contains(type.getRawType())) {
            // Workaround for https://github.com/google/gson/issues/1570 - END
        return null;
    }
...

@Marcono1234
Copy link
Collaborator

Marcono1234 commented Aug 20, 2022

Does #2032 describe your issue? (edit: it is related)

@Marcono1234
Copy link
Collaborator

This issue unfortunately still exists, even with #1787 being merged. For backward compatibility this specific case was not fixed, see #1787 (comment).

As workaround for the specific case described in this issue it might be possible to use RuntimeTypeAdapterFactory.recognizeSubtypes(), which was added by #2160.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants