3

I have an existing Request/Response protocol using JSON that I have no control over.

Example 1: response JSON not requiring any polymorphic deserialisation

{
  "name" : "simple_response"
  "params" : {
    "success" : true
  }
}

Example 2: response JSON requiring polymorphic deserialisation of params property

{
  "name" : "settings_response",
  "params" : {
    "success" : true,
    "settings" : "Some settings info"
  }
}

My class structure looks like this:

class Response { // Not abstract. Used if no specialized response properties needed
  @JsonProperty("params")
    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
            property = "name")
    @JsonSubTypes({
            @JsonSubTypes.Type(value=GetSettingsResponseParams.class, name="settings_response")
    })
  Params params;
  String name; // Need to use its value to determine type of params
}

class Params {
  boolean success;
}

class GetSettingsResponseParams extends Params {
  String settings;
}

When I try to deserialise the JSON in "Example 2" I get:

Unexpected token (END_OBJECT), expected VALUE_STRING: need JSON String that contains type id (for subtype of com.foo.Params)

What am I doing wrong and how can I fix it?

Farrukh Najmi
  • 5,055
  • 3
  • 35
  • 54

1 Answers1

2

Response model should look like:

class Response {

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "name", visible = true)
    @JsonSubTypes({
            @JsonSubTypes.Type(value = GetSettingsResponseParams.class, name = "settings_response"),
            @JsonSubTypes.Type(value = Params.class, name = "simple_response")
    })
    private Params params;
    private String name;

    // getters, settets, toString, etc.
}

Above model works properly for two presented JSON payloads.

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • Michal Zlober, Sorry I had a mistake in my sample json. The name property is a sibling of param property and that is why I am using 'include = JsonTypeInfo.As.EXTERNAL_PROPERTY' on JsonTypeInfo. Looking for a solution that constraint of my existing api. Sorry for the mistake. – Farrukh Najmi Nov 25 '19 at 18:49
  • @FarrukhNajmi, in that case `EXTERNAL_PROPERTY` make sense. I tried my version of `Response` class with your classes and they work like expected for given payloads. Which version of `Jackson` do you use? – Michał Ziober Nov 25 '19 at 22:13
  • 1
    @MichalZlober, Thank you very much for taking the time to help me resolve this issue with a very clear example. I had several issues in my code. Missing visible = true in JsonTypeInfo was one. Another was a missing JsonProperty on a property that had a different name in my Params class. – Farrukh Najmi Dec 02 '19 at 15:40