riot
riot

Reputation: 556

Dynamically create an object based on a field

I receive from a network API a JSON like this one:

{
  ...
  "foobar":
    {
      "type": "...",
      "keyTypeA": "value"
    }
}

With foobar having different object types depending on its type field. So, foobar can be:

{
  "type": "typeA",
  "keyA1": "...",
  "keyA2": "...",
  ...
}

or

{
  "type": "typeB",
  "keyB1": "...",
  "keyB2": "...",
  ...
}

etc.

How can I parse these JSON models into my POJO classes defined here:

public class FoobarTypeBase {
    @SerializedName("type")
    public String type;
}

public class FoobarTypeA extends FoobarTypeBase {
    @SerializedName("keyA1")
    public SomeObject keyA1;
    @SerializedName("keyA2")
    public SomeObject keyA2;
}

public class FoobarTypeB extends FoobarTypeBase {
    @SerializedName("keyB1")
    public SomeObject keyB1;
    @SerializedName("keyB2")
    public SomeObject keyB2;
}

I guess I have to deal with TypeAdapterFactory and TypeAdapter but I don't known how to do it efficiently.

Upvotes: 1

Views: 444

Answers (1)

Samuele Pontremoli
Samuele Pontremoli

Reputation: 594

I usually use a combination of Retrofit + Gson and do it this way:

RuntimeTypeAdapterFactory<FoobarTypeBase> itemFactory = RuntimeTypeAdapterFactory
            .of(FoobarTypeBase.class, "type") // The field that defines the type
            .registerSubtype(FoobarTypeA.class, "foobar")
            .registerSubtype(FoobarTypeB.class) // if the flag equals the class name, you can skip the second parameter.

Gson gson = new GsonBuilder()
            .registerTypeAdapterFactory(itemFactory)
            .create();

Then I initialize Retrofit like this:

Retrofit.Builder builder = new Retrofit.Builder();
    builder.baseUrl(BASE_URL);
    builder.addConverterFactory(GsonConverterFactory.create(gson));

Retrofit retrofit = builder.build();

Upvotes: 2

Related Questions