问题描述
我们有一个在 Apache TomEE 上运行的 JAX-RS 应用程序.我们稍微自定义了默认的 Jettison 提供程序,以更好地遵守 JavaScript 前端使用的 JSON 约定.TomEE 允许通过它的 resources.xml 文件来实现:
We've got a JAX-RS application that runs on Apache TomEE. We slightly customize the default Jettison provider to better adhere to JSON conventions used by JavaScript frontend. TomEE allows to do it via its resources.xml file:
<resources>
<Service id="jettison" class-name="org.apache.cxf.jaxrs.provider.json.JSONProvider">
serializeAsArray = true
dropRootElement = false
arrayKeys = members,roles
supportUnwrapped = true
writeXsiType = false
</Service>
</resources>
现在我们正在迁移到 GlassFish v4.1,我们注意到 JSON 输出与我们在 TomEE 中的不同 - 因此完全破坏了前端.我正在寻找类似的机制来自定义 GlassFish 中的 JSON 编组器.事实上,我已经有点坚持与 Jersey、MOXy、Jackson,抛弃.我们如何知道实际使用的是哪个 JSON 提供程序?我们如何选择一个?我们如何自定义行为?
Now we are migrating to GlassFish v4.1, and we notice that JSON output differs from what we had in TomEE - thus completely breaking frontend. I'm looking for similar mechanism to customize JSON marshaller in GlassFish. In fact, I'm already a little bit stuck with Jersey, MOXy, Jackson, Jettison. How do we know which JSON provider is actually used? How do we select one? How do we customize the behavior?
该应用程序是纯 JAX-RS,不直接使用任何 JSON 处理器,而是依赖于 JAXB 注释类的编组.引入任何非 JavaEE 依赖项是非常不可取的,因为应用程序旨在跨容器(TomEE、GlassFish、某天 WildFly)可移植.配置文件方法,类似于TomEE,更可取;编程方式也是可以接受的 - 但前提是保持可移植性.
The application is pure JAX-RS and does not use any JSON processor directly, instead relying on marshalling of JAXB-annotated classes. Introduction of any non-JavaEE dependencies is highly undesirable, since the application is intended to be portable across containers (TomEE, GlassFish, some day WildFly). Config-file method, similar to TomEE, is preferable; programmatic way is acceptable, too - but only if portability is maintained.
推荐答案
Glassfish 使用 MOXy 作为默认提供程序.它在内部有处理 Jackson、Jettison 和 MOXy 的库,但默认是 MOXy.有两种方法可以禁用 MOXy
Glassfish uses MOXy as the default provider. Internally it has the libraries to handle Jackson, Jettison, and MOXy, but the default is MOXy. There are two ways to disable MOXy
- 设置 Jersey 属性
jersey.config.server.disableMoxyJson
到true
. - 注册一个不同的
XxxJsonFeature
来禁用 MOXy.例如JacksonFeature
带有jersey-media-json-jackson
- Set the Jersey property
jersey.config.server.disableMoxyJson
totrue
. - Register a different
XxxJsonFeature
that disables MOXy. For instance theJacksonFeature
that comes withjersey-media-json-jackson
请注意,Glassfish 带有 Jackson 提供程序,但它是 Jackson 1.x.如果您想使用 2.x,而不是使用上面列出的 jersey-media-json-jackson
依赖项,最好使用底层的 Jackson 提供程序依赖项,即
Note that Glassfish comes with a Jackson provider, but it is Jackson 1.x. If you want to use 2.x, instead of the using the jersey-media-json-jackson
dependency listed above, it would be better to use the underlying Jackson provider dependency, which is
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.6.0</version>
</dependency>
您可以注册 JacksonJsonProvider
或 JacksonJaxbJsonProvider
以获得 JAXB 注释支持.
You can register the JacksonJsonProvider
or the JacksonJaxbJsonProvider
for JAXB annotation support.
要配置 Jackson,这是实现 ContextResolver
的最简单方法,如此答案中所示.JacksonJsonProvider
将查找此 ContextResolver
以检索用于(反)序列化的 ObjectMapper
.
To configure Jackson, the easiest way to implement a ContextResolver
, as seen in this answer. The JacksonJsonProvider
will lookup this ContextResolver
to retrieve the ObjectMapper
used for (de)serialization.
您还需要记住禁用 MOXy,如上所述.
You will also need to remember to disable MOXy, as mentioned above.
还有一点需要注意的是,这个解决方案是可移植的.使用 JAX-RS,唯一可移植的应用程序配置是通过 Application
子类
Also one thing to note is that this solution is portable. With JAX-RS, the only portable application configuration is through an Application
subclass
@ApplicationPath("/api")
public class MyApplication extends Application {}
话虽如此,在 Glassfish 的情况下禁用 MOXy 无非是设置属性.在 Application
类中,您可以覆盖 getProperties()
,它返回一个 Map
.您可以在此处设置属性.并且因为它只不过是一个字符串(没有外部依赖项),所以它仍然是可移植的
That being said, the disabling of MOXy in the case of Glassfish, is nothing more than setting a property. In the Application
class, you can override getProperties()
which returns a Map<String, Object>
. This is where you can set the property. And because it s nothing more than a String (no outside dependencies), it remains portable
@ApplicationPath("/api")
public class MyApplication extends Application {
@Override
public Map<String, Object> getProperties() {
Map<String, Object> props = new HashMap<>();
props.put("jersey.config.server.disableMoxyJson", true);
return props;
}
}
就上面的Jackson依赖而言,也是一个可移植的解决方案.它没有特定于 (JAX-RS) 实现.它实现并使用标准的 JAX-RS API
As far as the above Jackson dependency, it is also a portable solution. It it nothing (JAX-RS) implementation specific. It implements and uses standard JAX-RS APIs
这篇关于使用 GlassFish v4 自定义 JSON 编组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!