简体   繁体   中英

Polymorphic JSON deserialization (Jackson) of entity parameters (Google Cloud Endpoints)

I have a Cloud Endpoints API method which takes an entity parameter (ie JSON request body mapping to a POJO). This object contains a field who's type is an abstract class, ie:

public class APIRequest {
  public String customerName;

  public BaseFilter filter;
}

The aforementioned API method has the following signature:

public SomeResponsePOJO doTheThing(User user, APIRequest requestEntity)

Now, according to Jackson's documentation , it should be possible to annotate the abstract class in such a way that, when deserialising, an instance of the appropriate concrete class is created, controlled by an additional type parameter on the request.

As per the documentation, I've annotated the abstract class as follows:

@JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="filterType")
@JsonSubTypes({
  @Type(value = PeriodFilter.class, name = "Period")
})
public abstract class BaseFilter {
  ...
}

Where PeriodFilter is a concrete subclass of BaseFilter:

public class PeriodFilter extends BaseFilter {
  private Date startDate;
  private Date endDate;

  ...
}

A request is then made with the following body:

{
  "customerName": "Derp Pty Ltd",
  "filter": {
    "filterType": "Period",
    "startDate": "2016-01-01",
    "endDate": "2016-01-31"
  }
}

Unfortunately, GAE responds with the following error:

com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException:
  Can not construct instance of <package name>.BaseFilter, problem:
    abstract types can only be instantiated with additional type information
    at [Source: N/A; line: -1, column: -1]
    (through reference chain: <package name>.APIRequest[\"filter\"])

As far as I can tell from the documentation, I've done everything required for this to work. Unless I'm missing something, the error above would suggest that AppEngine is ignoring the Jackson annotations.

Have I missed something, or is what I'm trying to do simply not supported with Cloud Endpoints?

Thanks to @BrendanMolloy for pointing out the related question regarding GAE ignoring Jackson's annotations. I had overlooked that Google repackages Jackson, hence it was looking for its own instances of the annotations, not those from Jackson proper.

Importing the annotations from the repackaged version of Jackson works as expected, but is obviously less than ideal -prone to break without notice if Google changes things on their end.

It would seem that using @ApiTransformer and Jackson's ObjectMapper in the Transformer implementation would be the best approach, as much as it would have been preferable to simply use @JsonTypeInfo directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM