获取 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>
所以有几件事阻止了你。
javax.json
(或 JSONP)不处理 POJO。它只处理 javax.json
API。如果您期望原始提供者处理 POJO,而 JSONP 提供者处理 javax.json
,那么它不会那样工作。您将使用处理 POJO 的那个(它不知道 javax.json
,或者您使用处理 javax.json
的那个。(我们确实在下面实现了这一点 :-)
Glassfish 的默认提供程序是 MOXy。所以我们需要禁用以使用任何其他提供程序。要禁用 MOXy,您需要设置此 属性
到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;
}
}
就是这样。我已经测试过了,它应该可以工作。
我想让 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>
所以有几件事阻止了你。
javax.json
(或 JSONP)不处理 POJO。它只处理javax.json
API。如果您期望原始提供者处理 POJO,而 JSONP 提供者处理javax.json
,那么它不会那样工作。您将使用处理 POJO 的那个(它不知道javax.json
,或者您使用处理javax.json
的那个。(我们确实在下面实现了这一点 :-)Glassfish 的默认提供程序是 MOXy。所以我们需要禁用以使用任何其他提供程序。要禁用 MOXy,您需要设置此 属性
到
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;
}
}
就是这样。我已经测试过了,它应该可以工作。