使用Jackson ObjectMapper和Jersey

编程入门 行业动态 更新时间:2024-10-21 04:16:29
本文介绍了使用Jackson ObjectMapper和Jersey的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在使用Jersey 2.4创建一个简单的REST接口来提供JSON对象。我的问题是我正在尝试使用fastxml Jackson注释来控制输出,这对我不起作用。我已将注释放入我的bean类中,但它们会被忽略。

I'm using Jersey 2.4 to create a simple REST interface that serves up a JSON object. My problem is that I'm trying to use the fasterxml Jackson annotations to control the output and this is not working for me. I have put the annotations into my bean class but they are ignored.

当我显式创建一个ObjectMapper并使用它来对Java bean进行字符串化时,我得到了我的输出希望,尊重杰克逊的注释。但是,我希望我不必执行此步骤,以便我的资源类可以简单地返回bean,并且Jersey框架负责对其进行字符串化。

When I explicitly create an ObjectMapper and use this to stringify the Java bean, I get the output that I want, which respects the Jackson annotations. However, I would prefer that I don't have to do this step so that my resource class can simply return the bean and the Jersey framework takes care of stringifying it.

我试图使用 Custom ObjectMapper的答案来解决这个问题然而,对于Jersey 2.2和Jackson 2.1来说,这似乎并不适用于我。我看到ContextResolver已经创建,但它永远不会被调用。

I have tried to solve this using the answer from Custom ObjectMapper with Jersey 2.2 and Jackson 2.1, however, this does not appear to work for me. I see that the ContextResolver is created but it is never called.

我也花了很多时间试图解决这个看似简单的问题。我把它剥离到一个非常简单的测试用例,如下所示。在解决这个问题上,我将不胜感激。

I have also spent many hours trying to solve this apparently simple problem. I have stripped this down to a very simple test case, which is shown below. I would appreciate any help at all in resolving this.

资源Java类:

@Path("resource") public class MainResource { public static class Foobar { @JsonIgnore private String foo = "foo"; private String baa = "baa"; private Map<String, List<? extends Number>> map = new HashMap<>(); public Foobar() { map.put("even", Arrays.asList(new Integer[] { 2, 4, 6, 8, 10 })); map.put("odd", Arrays.asList(new Integer[] { 1, 3, 5, 7, 9 })); map.put("float", Arrays.asList(new Float[] { 1.1F, 2.2F, 3.3F })); } public String getFoo() { return foo; } public void setFoo(String foo) { this.foo = foo; } public String getBaa() { return baa; } public void setBaa(String baa) { this.baa = baa; } @JsonAnyGetter public Map<String, List<? extends Number>> getMap() { return map; } public void setMap(Map<String, List<? extends Number>> map) { this.map = map; } } private ObjectMapper om = new ObjectMapper(); @GET @Path("get-object") @Produces(MediaType.APPLICATION_JSON) public Foobar getObject() { // In this method, I simply return the bean object but the WRONG JSON syntax is generated. return new Foobar(); } @GET @Path("get-string") @Produces(MediaType.APPLICATION_JSON) public String getString() throws JsonProcessingException { // This method returns the RIGHT JSON syntax but I don't want to have to explicitly use the ObjectMapper. Foobar foobar = new Foobar(); return om.writeValueAsString(foobar); } }

web.xml:

<web-app version="3.0" xmlns="java.sun/xml/ns/javaee" xmlns:xsi="www.w3/2001/XMLSchema-instance" xsi:schemaLocation="java.sun/xml/ns/javaee java.sun/xml/ns/javaee/web-app_3_0.xsd"> <module-name>sample</module-name> <servlet> <servlet-name>Jersey Web Application</servlet-name> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> <init-param> <param-name>jersey.config.server.provider.packages</param-name> <param-value>ie.cit.nimbus.sample</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>Jersey Web Application</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>

POM依赖项:

<dependencies> <dependency> <groupId>com.fasterxml.jackson.jaxrs</groupId> <artifactId>jackson-jaxrs-json-provider</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.glassfish.jersey.ext</groupId> <artifactId>jersey-spring3</artifactId> <version>2.4.1</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>2.4.1</version> </dependency> </dependencies>

推荐答案

编辑:Don'使用旧方法,因为它产生错误(至少与Android设备有关,请参阅EDIT2了解更多详情)。在我的测试中,Jersey v2.6似乎用 @Provide 解决了这个问题,这种方法不起作用。我能够使用这个简单的提供程序:

EDIT: Don't use the old approach below as it produces bugs (at least with with android device, see EDIT2 for more details). As of my tests, Jersey v2.6 seems to fix the problem with the @Provide, which approach did not work. I was able to get it work with this simple provider:

@Provider public class JerseyMapperProvider implements ContextResolver<ObjectMapper> { private static ObjectMapper apiMapper = ObjectMapperManager.createMapperForApi(); @Override public ObjectMapper getContext(Class<?> type) { return apiMapper; } }

所以请不要使用下面的黑客。

So please don't use my hack from below.

OLD APPROACH

使用

@Provider public class MyObjectMapperProvider implements ContextResolver<ObjectMapper>

对我不起作用(Jersey 2.4& Jackson 2.3)也许这是因为杰克逊提供商在代码中报告了 ContextResolver 应该在 JacksonJsonProvider.java (2.3rc1)中注册的错误:

was not working for me (Jersey 2.4 & Jackson 2.3) and maybe this is due to a in the jackson provider reported bug in the code where the ContextResolver should be registered in JacksonJsonProvider.java (2.3rc1):

@Override protected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType) { if (_providers != null) { ContextResolver<ObjectMapper> resolver = _providers.getContextResolver(ObjectMapper.class, mediaType); /* Above should work as is, but due to this bug * [jersey.dev.java/issues/show_bug.cgi?id=288] * in Jersey, it doesn't. But this works until resolution of * the issue: */ if (resolver == null) { resolver = _providers.getContextResolver(ObjectMapper.class, null); } if (resolver != null) { return resolver.getContext(type); } } return null; }

但至少我无法访问 jersey.dev.java/issues/show_bug.cgi?id=288 ,所以我不知道这个bug到底是什么。

But at least I cannot access jersey.dev.java/issues/show_bug.cgi?id=288, so I don't know what this bug is about.

但是我找到了一个解决方法(如果你愿意,那就是黑客)。只需使用正确的注释扩展 JacksonJsonProvider 并返回 ObjectMapper ,如下所示:

But I found a workaround (a hack if you so will). Just extend JacksonJsonProvider with the proper annotation and return your ObjectMapper like this:

@Provider @Consumes(MediaType.APPLICATION_JSON) // NOTE: required to support "non-standard" JSON variants @Produces(MediaType.APPLICATION_JSON) public class JacksonHackProvider extends JacksonJsonProvider { @Override protected ObjectMapper _locateMapperViaProvider(Class<?> type, MediaType mediaType) { return new MyCustomObjectMapper(); } }

无需做任何会自行注册的事情(检查使用日志,它将在您第一次访问json休息服务时注册)。现在这对我有用,不优雅,但我放弃了。

No need to do anything it will register itself (check with log, it will register the first time you access a json rest service). This is now working for me, not elegant, but I gave up.

编辑:谨慎使用 - 我遇到了一个可能与此黑客有关的错误:Android凌空无法发送一个带有请求主体的POST / PUT请求,总是从框架中得到400,我将调查并报告我的发现。

Use with caution - Im experiencing a bug maybe related to this hack: Android volley cannot send a POST/PUT request with a request body, always getting 400 from the framework, I will investigate and report my findings.

EDIT2:这个hack确实对通用负责每当一个带有凌空和 OKHTTP 客户端的Android应用程序尝试执行POST或PUT请求时,请不要使用此 - 在我的测试中,2.6似乎解决了这个问题,所以你可以使用 @Provide 方法

This hack was indeed responsible for a generic 400 whenever an Android app with volley and OKHTTP client tried tried to do a POST or PUT request so don't use this - in my test jersey 2.6 seems to fix this so you can use @Provide approach

更多推荐

使用Jackson ObjectMapper和Jersey

本文发布于:2023-10-31 06:17:17,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1545263.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Jackson   ObjectMapper   Jersey

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!