获取 JAX-RS 服务以使用 JsonObject 创建对象 属性

Getting JAX-RS service to create an object with a JsonObject property

我想让 JAXRS 将特定 class 属性 的所有 json 详细信息推送到 JsonObject 对象中。

假设我有以下 class:

public class MyMessage implements Serializable {

    private PayloadType payloadType;    

    private JsonObject payload;
}

REST 方法:

@POST
@Path("/send")
@Consumes(MediaType.APPLICATION_JSON)
public Response send(MyMessage message) 

我想 POST 以下 JSON,但将 payload 属性 设置为 javax.json.JsonObject 对象。

{
   payloadType:'MESSAGE',
   payload:{
      subject:"My Subject",
      body:"This is a message"
   }
}

我在 Glassfish 上 运行,所以我期待 JsonObject 的消息 reader 包含在 org.glassfish.jersey.media 中,这是包含在GF4.1。添加以下 Maven 依赖项只会导致模棱两可的 class 异常。

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-processing</artifactId>
    <version>2.22.1</version>
</dependency>

所以有几件事阻止了你。

  1. javax.json(或 JSONP)不处理 POJO。它只处理 javax.json API。如果您期望原始提供者处理 POJO,而 JSONP 提供者处理 javax.json,那么它不会那样工作。您将使用处理 POJO 的那个(它不知道 javax.json,或者您使用处理 javax.json 的那个。(我们确实在下面实现了这一点 :-)

  2. Glassfish 的默认提供程序是 MOXy。所以我们需要禁用以使用任何其他提供程序。要禁用 MOXy,您需要设置此 属性

    ServerProperties.MOXY_JSON_FEATURE_DISABLE

    true。在您的 web.xml 或 Java 配置中。

因此,为了使这项工作正常进行,我们应该确保我们使用的是 Jackson。 Jackson 有 jackson-datatype-jsr353 模块,它允许做你想做的事情,javax.json 在 POJO 中。

Glassfish 已经有了 Jackson 提供程序,但无论如何您都应该将其添加到 provided 范围内。所以添加这两个依赖

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.10.4</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr353</artifactId>
    <version>2.3.3</version>
</dependency>

如果你注意版本,我使用的是 Glassfish 4.1 中包含的相同版本。它使用 Jersey 2.10.4 和 Jackson 2.3.3。您希望版本发生冲突。即使提供了 jersey-media-json-jackson,编译时尝试使用与服务器相同的版本仍然是个好主意。

您还应该在您的应用程序中注册 JacksonFeature

我们需要做的最后一件事是注册 JSR353Module 以便我们可以获得 javax.json 对 Jackson 的支持。为此,只需在您的应用程序中注册以下提供商。

@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {

    private final ObjectMapper mapper;

    public ObjectMapperProvider() {
        mapper = new ObjectMapper();
        mapper.registerModule(new JSR353Module());
    }

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

就是这样。我已经测试过了,它应该可以工作。