【问题标题】:JAX-RS How to serialise JSON objects that are embedded within a common wrapper object and deserialise without the wrapperJAX-RS 如何反序列化嵌入在通用包装器对象中的 JSON 对象并在没有包装器的情况下反序列化
【发布时间】:2017-04-22 22:05:05
【问题描述】:

我打算像这样将 JSON 数据发送到我的 JAX-RS 端点:

POST /myendpoint

{
  "field1": "something",
  "field2": "something else",
  "field3": 12345
}

然后,当我检索一个对象时,我希望它包含在一个通用包装器中:

GET /myendpoint

{
  "type": "MyEndpoint"
  "items": [
    {
      "item":     {
        "id": 1,
        "field1": "something",
        "field2": "something else",
        "field3": 12345
      },
      "link": "https://api.site.com/myendpoint/1"
    },
    {
      "item":     {
        "id": 2,
        "field1": "different",
        "field2": "different else",
        "field3": 67890
      },
      "link": "https://api.site.com/myendpoint/2"
    }
  ],
  "page_size": 10,
  "page": 1,
  "total": 2,
  "message": ""
}

GET /myendpoint/2

{
  "type": "MyEndpoint"
  "items": [
    {
      "item":     {
        "id": 2,
        "field1": "different",
        "field2": "different else",
        "field3": 67890
      },
      "link": "https://api.site.com/myendpoint/2"
    }
  ],
  "page_size": 10,
  "page": 1,
  "total": 1,
  "message": ""
}

我开始在 Jersey 中使用 Jackson FasterXML 进行自动序列化/反序列化,即:

@Provider
public class JsonObjectMapperProvider implements ContextResolver<ObjectMapper> {

    private final ObjectMapper objectMapper;

    public JsonObjectMapperProvider() {
        objectMapper = new ObjectMapper();
    }

    @Override
    public ObjectMapper getContext(final Class<?> type) {
        return objectMapper;
    }

}

然后在资源中:

@POST
@Consumes(MediaType.APPLICATION_JSON)
public void createMyEndpoint(MyEndpoint myEndpoint) {
    myEndpointDao.create(myEndpoint);
    // ...
}

@GET
@Produces(MediaType.APPLICATION_JSON)
public List<MyEndpoint> createMyEndpoint() {
    // I'm not actually sure how to do this one yet!! but I include it for completeness
    return myEndpointDao.getAll();
}

@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public MyEndpoint createMyEndpoint(@PathParam("{id}") id) {
    return myEndpointDao.read(id);
}

这适用于未包含在包装器中的 MyEndpoint 对象,但我将如何包含包装器?还是有更好的方法来做到这一点?

JSON 的架构并不是一成不变的,如果还有什么更有意义的,那我就听好了。

【问题讨论】:

  • 哪个版本的 jax-rs,2.0?
  • 是的 JAX-RS 2.0,我使用的是 Jersey 2.25.1

标签: java json jersey jackson jax-rs


【解决方案1】:

在这里,我写了一些我在阅读您的问题时想到的建议:

  1. 总是从你的方法中返回一些东西,即使你正在处理一个 POST 方法。这将使调用者知道请求状态。
  2. 而不是返回你的模型对象,我认为如果你的方法总是返回一个对象javax.ws.rs.core.Response会更好
  3. 如果您担心序列化(我的意思是使用包装器),只需使用Response 对象来序列化您的响应。例如对于成功响应使用:Response.ok().entity(yourReturnObject).build(),这将几乎透明地处理序列化部分(您不需要处理 objectMapper)。

这可能是一个简单的方法示例:

@GET
@Path("/{id}")
@Produces({ "application/json" })
public Response createMyEndpoint(@PathParam("id") String id) {
    try {
        return Response.ok().entity(myEndpointDao.read(id)).build();
    } catch (Exception e) {
       Response.status(500).entity(e.getMessage()).build();
    }
}

我还建议,为了让你的生活更简单,看看swagger

【讨论】:

  • 我最初完全误读了您的答案;我错误地认为通过返回 Response 我丢弃了自动 JSON 序列化,让我对(你甚至说)我不是这样的事实视而不见。我继续研究,得出了同样的结论。重新阅读您的答案后,我意识到解决方案一直都在这里,而且我使用包装器 POJO 的事实也无关紧要,因为如果使用泛型,例如 MyWrapper&lt;MyType&gt; wrapper = new MyWrapper&lt;&gt;(); 然后 return Response.status(Response.Status.CREATED).entity(wrapper).build();,Jackson 可以无缝处理这个问题。
  • 至少现在我有信心并说服自己这是正确的前进方式,这总是好的:)
  • @Neilos 很高兴并且很满意你发现我的答案是正确的;)
猜你喜欢
  • 1970-01-01
  • 2015-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-20
  • 2016-12-05
  • 2014-10-24
相关资源
最近更新 更多