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

Generic classes with type parameters parsing/serializing #49

Open
zoltish opened this issue Mar 18, 2015 · 2 comments
Open

Generic classes with type parameters parsing/serializing #49

zoltish opened this issue Mar 18, 2015 · 2 comments

Comments

@zoltish
Copy link

zoltish commented Mar 18, 2015

Aloha!

For a big project of mine my data is stored as such:

abstract class A <T1, T2> {
    T1 first;
    T2 second;
    ...other simple fields...
}

class B<This,That>{
}

Since the scope for the data is so wide there are N number of classes that all depend on A like this. In GSON I use TypeAdapters to include the class name of each subclass in the json so that it can be read back properly, Id like to see something similar in LoganSquare.

I cannot get it to work the way LoganSquare is built at the moment (If its supported at all?) as it always tries to create instances of A directly.

Thanks!

@eirnym
Copy link

eirnym commented Nov 17, 2015

👍

@mannodermaus
Copy link
Contributor

LoganSquare, at this point, is able to handle generics for the kind of scenario you describe. Just make sure to annotate both the abstract base class and its sub-classes properly and you're good to go:

@JsonObject
public abstract class A<T1, T2> {

    @JsonField
    T1 first;

    @JsonField
    T2 second;
}

@JsonObject
public class B extends A<String, String> {

    @JsonField
    int somethingElse;
}

With this setup, you can serialize and parse like this:

B model = new B("Item A", "Item B", 100);
String json = LoganSquare.serialize(model);
System.out.println(json);    // prints "{"somethingElse":100,"first":"Item A","second":"Item B"}"

If you need to include type information for each class as well (even though you don't need to with LoganSquare), this works by adding a Class @JsonField to the abstract base class with a custom type converter:

@JsonObject
public abstract class A<T1, T2> {

    // (the rest from above...)

    // Use "Class" without any type variable for the field; assign it e.g. in the constructor ("this.type = getClass();")
    @JsonField(typeConverter = ClassConverter.class)
    Class type;
}

public final class ClassConverter implements TypeConverter<Class> {

    @Override
    public Class parse(JsonParser jsonParser) throws IOException {
        try {
            return Class.forName(jsonParser.getValueAsString());
        } catch (ClassNotFoundException e) {
            throw new IOException(e);
        }
    }

    @Override
    public void serialize(Class object, String fieldName, boolean writeFieldNameForObject, JsonGenerator jsonGenerator) throws IOException {
        jsonGenerator.writeFieldName(fieldName);
        jsonGenerator.writeString(object.getCanonicalName());
    }
}

With this setup, the code snippet above prints {"somethingElse":100,"first":"Item A","second":"Item B","type":"your.full.package.name.B"}.

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

No branches or pull requests

3 participants