我编写了一个休息服务API,它以一种地图布局的形式返回数据结构。映射条目可以来自String,Integer或Date类型。其余服务方法支持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相似吗?
有趣的是,当我使用请求标头'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>
Wildfly 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格式?
答案 0 :(得分:4)
如果我们要测试模型类会有所帮助,所以我们可以看到哪些提供者产生了哪些结果(在测试时)。但如果没有它,我只会提出一些需要考虑的事情
Glassfish默认使用MOXy来支持JSON / POJO。我个人不喜欢使用MOXy。起初我提升了它的用法,因为它是泽西岛推荐的,但过了一段时间,你开始了解它的局限性。 Glassfish还附带Jackson支持,但我们需要明确禁用MOXy,或者只注册Jackson功能(不可移植)或者添加杰克逊提供商的混合MOXy 和。
就Wildfly而言,提到的一件事要考虑here in the Resteasy Documentation
21.6。可能与JAXB提供程序冲突
如果您的Jackson类使用JAXB注释进行注释,并且您的类路径中有
resteasy-jaxb-provider
[Wildfly附带的],则可以触发Jettision JAXB编组代码。要关闭JAXB json marshaller,请使用类上的@org.jboss.resteasy.annotations.providers.jaxb.IgnoreMediaTypes("application/*+json")
。
另一件需要考虑的事情是两台服务器都附带了Jackson 1.x和Jackson 2.x的提供商。哪一个使用过的编组结果可能没有区别,但与本答案的下一部分有关(另见here - 虽然这提到了JBoss AS7,但我不确定它是否适用于Wildfly。我认为 Wildfly默认使用Jackson 2。
测试使用哪个提供程序的一种方法是创建ContextResolver
。现在,下一个示例仅用于测试目的(您通常不会自己添加Jackson,但杰克逊提供商)。
将此依赖项添加到项目中
<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;
}
}
结果
Glassfish:杰克逊2未被使用
Wildfly:使用了Jackson 2(即使使用JAXB注释。也许你需要明确地在项目类路径中明确地使用resteasy-jaxb-provider以便Jettison启动。)
那么我们如何以便携方式修复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。
此解决方案已在Wildfly 8.1和Glassfish 4.0上进行了测试
答案 1 :(得分:3)
JAX-RS指定用于序列化实体的接口MessageBodyWriter,但这仅定义了将Java对象转换为OutputStream。结果如何取决于您或JAX-RS运行时。
RESTeasy和Jersey都提供了类似application/json
或application/xml
等媒体类型的序列化程序,以及未找到更好的序列化程序时使用的默认序列化程序。
为了将Java对象序列化为XML,标准为JAXB,因此结果应该不同(太多)。对于JSON,情况有所不同,没有明确的标准,但有许多序列化器,例如:
他们处理一些不同的事情可以用不同的方式配置,并在历史记录中改变行为。
回答最后一个问题:如果你在Wildfly上使用RESTeasy,你通常会使用Jackson,你可以configure a lot。这是an example。
请注意,Jackson配置选项已不时重命名。