json - 为什么 Rest-Easy 和 Jersey 有不同的 JSON 输出格式?

标签 json glassfish jersey jax-rs resteasy

我已经编写了一个 rest 服务 API,它返回一种 map 布局的数据结构。映射条目可以来自字符串、整数或日期类型。其余服务方法支持 XML 和 Json 输出。

现在我认识到 GlassFish( Jersey )中的 JSON 结果与 Wildfly(Reas-Easy)中的不同

当使用 application/json 在 GlassFish 上运行其余服务时,输出如下所示:

{"entity":{"item":{"name":"$modified","value":{"@type":"xs:dateTime","$":"2015-02-17T22:33:57.634+01:00"}}}}

在 WildFly (Rest-Easy) 上的相同结果如下所示:

{"entity":[{"item":[{"name":"$modified","value":[1425822673120]}]}]}

有人可以解释这种行为吗?我希望 WildFly 中的输出应该类似于 GlassFish?

有趣的是,当我使用请求 header “application/xml”调用相同的方法时,两个系统都返回相同的(预期的)格式。

GlassFish XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<entity><item><name>$modified</name>
<value xsi:type="xs:dateTime">2015-02-17T22:33:57.634+01:00</value></item></entity></collection>

野蝇 XML:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><collection xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<entity><item><name>$modified</name>
<value xsi:type="xs:dateTime">2015-03-08T14:51:13.120+01:00</value></item></entity></collection>

有没有办法为 Rest-Easy 配置 JSON 格式?

最佳答案

如果我们有要测试的模型类会有所帮助,这样我们就可以看到哪些提供者产生了哪些结果(在测试时)。但是没有它,我只会抛出一些事情来考虑

Glassfish 默认使用 MOXy用于 JSON/POJO 支持。我个人不喜欢使用 MOXy。起初我推广它的用法,因为它是 Jersey 推荐的,但过了一段时间,你开始了解它的局限性。 Glassfish 也附带 Jackson 支持,但我们需要显式禁用 MOXy,或者只注册 Jackson 功能(不可移植),或者结合禁用 MOXy 添加 Jackson 提供程序。

就 Wildfly 而言,如前所述需要考虑一件事 here in the Resteasy Documentation

21.6. Possible Conflict With JAXB Provider

If your Jackson classes are annotated with JAXB annotations and you have the resteasy-jaxb-provider [which Wildfly comes shipped with] in your classpath, you may trigger the Jettision JAXB marshalling code. To turn off the JAXB json marshaller use the @org.jboss.resteasy.annotations.providers.jaxb.IgnoreMediaTypes("application/*+json") on your classes.

另一件需要考虑的事情是,这两款服务器都附带了 Jackson 1.x 和 Jackson 2.x 的提供程序。使用哪个在编码结果上可能没有差异,但与此答案的下一部分相关(另请参阅 here - 尽管这提到了 JBoss AS7,但我不确定它是否适用于 Wildfly。我 < em>think Wildfly 默认使用 Jackson 2)。

测试正在使用哪个提供程序的一种方法是创建一个 ContextResolver .现在,下一个示例仅用于测试目的(您通常不会单独添加 Jackson,而是添加 Jackson provider)。

将这个依赖添加到你的项目中

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.0</version>
</dependency>

添加这个类

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

@Provider
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper>{

    static final Logger logger 
                 = Logger.getLogger(ObjectMapperContextResolver.class.getName());
    final ObjectMapper mapper = new ObjectMapper();

    @Override
    public ObjectMapper getContext(Class<?> type) {
        logger.log(Level.INFO, "<===== ***** Jackon 2 is used ***** =====>");
        return mapper;
    } 
}

Result

Glassfish: Jackson 2 not being used
Wildfly: Jackson 2 is used (even with JAXB annotations. Maybe you need to explicitly have the resteasy-jaxb-provider explicitly on the project classpath for the Jettison to kick in).

那么我们如何以可移植的方式修复 Glassfish 部署呢?我能够测试并在两台服务器上使用 Jackson 2 的一种方法是通过添加服务器配置属性来禁用 MOXy。这是可移植的,因为该属性只不过是一个字符串。它会被 Resteasy 忽略。

@ApplicationPath("/rest")
public class AppConfig extends Application {

    @Override
    public Map<String, Object> getProperties() {
        Map<String, Object> properties = new HashMap<>();
        properties.put("jersey.config.disableMoxyJson", true);
        return properties;
    }
}

我们还需要将 Jackson 提供程序添加到项目中

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>2.4.0</version>
</dependency>

奇怪的是我们必须添加这个依赖项,因为 Glassfish 已经附带了它,但如果我不添加它,我会得到一个 MessageBodyWiter not found。

此解决方案已在 Wildfly 8.1 和 Glassfish 4.0 上进行测试

关于json - 为什么 Rest-Easy 和 Jersey 有不同的 JSON 输出格式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28929460/

相关文章:

javascript - 将数组连接到 Google Chart

javascript - 将给定格式的字符串转换为 json

java - 警告 : WEB9102: Web Login Failed: com. sun.enterprise.security.auth.login.common.LoginException:

java - 在 glassfish 服务器中运行项目时出现 web.xml SAXParseException 错误

java - 如何将 Apache Httpclient 与 Jersey 2.3 客户端一起使用

java - 如何将客户端发送的Base64图像存储在BlobStore中

java - 无法访问 Spring Boot 和 Jersey 应用程序中的某些 Controller

sql - JSON 对象查询 SQL Server

java - 部署 ear Web 应用程序时出现 Glassfish 错误

ios - 如何解析本地文件中的json数据?