json - 在 Jersey 2.2 下使用 JAXBElement 和 MOXy 进行 JSON 处理的问题

标签 json jaxb jersey moxy jaxbelement

我扩展了jersey-examples-moxy代码以使用XML模式定义而不是JAXB注释的bean。 xjc 编译的 XML 模式生成与原始示例相同的 XML 和 JSON 编码。

我按照 Jersey 说明进行操作,并使用 ObjectFactory 在 CustomerResource.java 中生成 JAXBElement Customer 对象表示形式。我还按照描述修改了客户端。我还纳入了 PUT issues with JSON processing using JAXB under Jersey 2.2 with MOXy 中描述的修复程序。

MediaType.APPLICATION_XML 功能完美,MediaType.APPLICATION_JSON 适用于 GET,但客户端无法在 PUT 上编码 JSON,并显示“MessageBodyWriter 未找到”。抛出以下异常:

testJsonCustomer(org.glassfish.jersey.examples.jaxbmoxy.MoxyAppTest)  Time elapsed: 0.113 sec  <<< ERROR!
org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException: MessageBodyWriter not found for media type=application/json, type=class javax.xml.bind.JAXBElement, genericType=class javax.xml.bind.JAXBElement.
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor$TerminalWriterInterceptor.aroundWriteTo(WriterInterceptorExecutor.java:191)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139)
at org.glassfish.jersey.filter.LoggingFilter.aroundWriteTo(LoggingFilter.java:268)
at org.glassfish.jersey.message.internal.WriterInterceptorExecutor.proceed(WriterInterceptorExecutor.java:139)
at org.glassfish.jersey.message.internal.MessageBodyFactory.writeTo(MessageBodyFactory.java:1005)
at org.glassfish.jersey.client.ClientRequest.writeEntity(ClientRequest.java:430)
at org.glassfish.jersey.client.HttpUrlConnector._apply(HttpUrlConnector.java:290)

以下是我修改 CustomerResource.java 的方法:

private static ObjectFactory factory = new ObjectFactory();

@GET
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public JAXBElement<Customer> getCustomer() {
    return factory.createCustomer(customer);
}

@PUT
@Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
@Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
public JAXBElement<Customer> setCustomer(Customer c) {
    customer = c;      
    return factory.createCustomer(customer);
}

以下是我发出 PUT 请求的方式(与功能 XML 相同):

@Override
protected void configureClient(ClientConfig clientConfig) {
    clientConfig.register(new MoxyXmlFeature());
}

@Test
public void testJsonCustomer() throws Exception {
    ObjectFactory factory = new ObjectFactory();
    final WebTarget webTarget = target().path("customer");

    // Target customer entity with GET and verify inital customer name.
    Customer customer = webTarget.request(MediaType.APPLICATION_JSON).get(Customer.class);
    assertEquals("Tom Dooley", customer.getPersonalInfo().getName());

    // Update customer name with PUT and verify operation successful.
    customer.getPersonalInfo().setName("Bobby Boogie");
    Response response = webTarget.request(MediaType.APPLICATION_JSON).put(Entity.json(factory.createCustomer(customer)));
    assertEquals(200, response.getStatus());

    // Target customer entity with GET and verify name updated.
    Customer updatedCustomer = webTarget.request(MediaType.APPLICATION_JSON).get(Customer.class);
    assertEquals(customer.getPersonalInfo().getName(), updatedCustomer.getPersonalInfo().getName());
}

感谢您的帮助!

最佳答案

您面临的问题在这一行:

Response response = webTarget.request(MediaType.APPLICATION_JSON).put(Entity.json(factory.createCustomer(customer)));

基本上,您将 JAXBElement 传递给 Entity#json 方法,但运行时没有有关泛型类型的信息,您需要提供它。这就是GenericEntity<T>类(class)的目的是:

webTarget
    .request(MediaType.APPLICATION_JSON)
    .put(Entity.json(new GenericEntity<JAXBElement<Customer>>(factory.createCustomer(customer)) {}));

关于json - 在 Jersey 2.2 下使用 JAXBElement 和 MOXy 进行 JSON 处理的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18409956/

相关文章:

c# - 提取键值对

javascript - 解析json时出错

java - JAX-B 中的映射序列化会产生不需要的 XML 命名空间和前缀

java - 如何使用 JAXB 返回 XML 文件

java - 使用 Springservlet 实现 Weblogic Rest 服务

json - 无法在 Neo4j 3.2.6 上调用 apoc.load.json

javascript - 在 knockout 中从 JSON 对象创建 ko.observableArray

java - 您可以有多组 JAXB 注释来编码/解码为不同的 XML 吗?

java - Dropwizard + jersey:原因:java.lang.IllegalStateException:不在请求范围内。为资源

java - 如何在 Jersey 调用之前获取与 URI 匹配的资源方法?