Is it possible to possible to achieve with Jersey a polymorphic deserialisation of json payloads on POST resources

核能气质少年 提交于 2019-12-11 16:56:19

问题


I'd like a endpoint to accept on a single verb and path a json payload that varies by a tiny bit and that can be mapped to different objects. The variation is usually on the field value like the grant_type in the OAuth world.

I scrapped stackoverflow and google on this, I found this among other

  • JAX-RS polymorphic POST request: how should I write my JSON?
  • Polymorphism in JSON, Jersey and Jackson

But those question don't seem to be relevant to me, jackson deserialisation alone works fine for this payloads, but Jersey always refuses to init the servlet with an error that let me thinks there's no way around it.

@Path("parent")
interface Resource {
    @POST
    @Path("test")
    String test(Payload1 payload1);

    @POST
    @Path("test")
    String test(Payload2 payload1);

    @Data
    @JsonTypeName("payload1")
    class Payload1 extends BasePayload {
        String a;
    }

    @Data
    @JsonTypeName("payload2")
    class Payload2 extends BasePayload {
        String b;
    }

//    @JsonTypeInfo(use= Id.MINIMAL_CLASS, include=As.PROPERTY, property="@class")
    @JsonTypeInfo(use= Id.NAME, include=As.PROPERTY, property="@payload")
    @JsonSubTypes({
                      @JsonSubTypes.Type(value = Payload1.class),
                      @JsonSubTypes.Type(value = Payload2.class)
    })
    class BasePayload {
    }

However I get this message in an exception upon servlet initialisation. (edited message for clarity)

</pre><p><b>root cause</b></p><pre>
org.glassfish.jersey.server.model.ModelValidationException: 
  Validation of the application resource model has failed during application initialization.

[[FATAL] A resource model has 
ambiguous (sub-)resource method for HTTP method POST and input mime-types as defined by
 "@Consumes" and "@Produces" annotations 
at Java methods 
 public java.lang.String xxx.Service.test(xxx.Resource$Payload1) 
and 
 public java.lang.String xxx.Service.test(xxx.Resource$Payload2) 
at matching regular expression /test. 

These two methods produces and consumes exactly the same mime-types and 
therefore their invocation as a resource methods will always fail.;
source='org.glassfish.jersey.server.model.RuntimeResource@59b668bf']

Note however that having a endpoint with the parent class of the payload works, but you have to handle the dispatch yourself.

@POST
@Path("test")
String test(BasePayload payload);

I'm using Spring-Boot 1.4 / Jersey 2.23.2 / Jackson 2.8.5


回答1:


The JAX-RS runtime uses the following for matching requests to resource methods:

  • URI: Defined in the @Path annotation.

  • Request method: Defined by a resource method designator such as @GET, @POST, etc).

  • Media type: Defined in Accept and Content-Type headers, that are matched with the values defined in the @Produces and @Consumes annotations, respectively.

The content of the payload is not taken into account, so it makes your first method definition ambiguous.

As you already figured out, the following approach is the way to go:

@POST
@Path("test")
String test(BasePayload payload);


来源:https://stackoverflow.com/questions/46369176/is-it-possible-to-possible-to-achieve-with-jersey-a-polymorphic-deserialisation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!