我如何使用Jersey JSON POJO支持?

时间:2011-03-01 23:01:09

标签: java json rest java-ee jersey

我有一个对象,我想在JSON中作为RESTful资源提供服务。我已经开启了Jersey的JSON POJO支持(在web.xml中):

<servlet>  
    <servlet-name>Jersey Web Application</servlet-name>  
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
        <param-value>true</param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>  
</servlet>  

但是当我尝试访问资源时,我得到了这个例外:

SEVERE: A message body writer for Java type, class com.example.MyDto, and MIME media type, application/json, was not found
SEVERE: Mapped exception to response: 500 (Internal Server Error)
javax.ws.rs.WebApplicationException
...

我正在尝试提供的课程并不复杂,只有一些公共最终字段和一个设置所有这些字段的构造函数。这些字段都是字符串,基元,与此类似的类或其列表(我尝试使用普通列表而不是通用列表&lt; T&gt; s,无济于事)。有谁知道是什么给出的?谢谢!

Java EE 6

泽西岛1.1.5

GlassFish 3.0.1

11 个答案:

答案 0 :(得分:15)

如果要使用JAXB注释,可以使用@XmlRootElement。(参见其他答案)。

但是,如果您更喜欢纯POJO映射,则必须执行以下操作(不幸的是,它不是用文档编写的):

  1. 将jackson * .jar添加到您的类路径中(如@Vitali Bichov所述);
  2. 在web.xml中,如果您使用com.sun.jersey.config.property.packages init参数,请将org.codehaus.jackson.jaxrs添加到列表中。这将包括泽西岛扫描列表中的JSON提供程序。

答案 1 :(得分:12)

Jersey-json有一个JAXB实现。您获得该例外的原因是您没有注册Provider,或者更具体地说是MessageBodyWriter。您需要在提供商中注册适当的上下文:

@Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
    private final static String ENTITY_PACKAGE = "package.goes.here";
    private final static JAXBContext context;
    static {
        try {
            context = new JAXBContextAdapter(new JSONJAXBContext(JSONConfiguration.mapped().rootUnwrapping(false).build(), ENTITY_PACKAGE));
        } catch (final JAXBException ex) {
            throw new IllegalStateException("Could not resolve JAXBContext.", ex);
        }
    }

    public JAXBContext getContext(final Class<?> type) {
        try {
            if (type.getPackage().getName().contains(ENTITY_PACKAGE)) {
                return context;
            }
        } catch (final Exception ex) {
            // trap, just return null
        }
        return null;
    }

    public static final class JAXBContextAdapter extends JAXBContext {
        private final JAXBContext context;

        public JAXBContextAdapter(final JAXBContext context) {
            this.context = context;
        }

        @Override
        public Marshaller createMarshaller() {
            Marshaller marshaller = null;
            try {
                marshaller = context.createMarshaller();
                marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            } catch (final PropertyException pe) {
                return marshaller;
            } catch (final JAXBException jbe) {
                return null;
            }
            return marshaller;
        }

        @Override
        public Unmarshaller createUnmarshaller() throws JAXBException {
            final Unmarshaller unmarshaller = context.createUnmarshaller();
            unmarshaller.setEventHandler(new DefaultValidationEventHandler());
            return unmarshaller;
        }

        @Override
        public Validator createValidator() throws JAXBException {
            return context.createValidator();
        }
    }
}

这将在提供的包名称中查找@XmlRegistry,该包名称包含@XmlRootElement个带注释的POJO。

@XmlRootElement
public class Person {

    private String firstName;

    //getters and setters, etc.
}

然后在同一个包中创建一个ObjectFactory:

@XmlRegistry
public class ObjectFactory {
   public Person createNewPerson() {
      return new Person();
   }
}

@Provider注册后,泽西岛应该为您的资源中的编组提供便利:

@GET
@Consumes(MediaType.APPLICATION_JSON)
public Response doWork(Person person) {
   // do work
   return Response.ok().build();
}

答案 2 :(得分:11)

这对我来说 - 泽西岛2.3.1

在web.xml文件中:

<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><my webapp packages>;org.codehaus.jackson.jaxrs</param-value>
</init-param>
</servlet>

在pom.xml文件中:

<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.3.1</version>
</dependency>

答案 3 :(得分:10)

我按照here说明了如何使用Jersey和Jackson POJO(而不是JAXB)。它也适用于Jersey 1.12。

答案 4 :(得分:3)

为什么使用最终字段? 我正在使用泽西,我有一些JAXB对象/ pojos,而我所要做的只是用@Produces(“application / json”)注释我的资源方法,它开箱即用。我没有弄乱web.xml。只需确保您的pojos正确注释。

这是一个简单的pojo

package test;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class SampleJaxbObject {

    private String field1;

    private Integer field2;

    private String field3;

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public Integer getField2() {
        return field2;
    }

    public void setField2(Integer field2) {
        this.field2 = field2;
    }

    public String getField3() {
        return field3;
    }

    public void setField3(String field3) {
        this.field3 = field3;
    }


}

答案 5 :(得分:3)

您可能已经想到了这一点,但您需要做的就是将这些杰克逊罐添加到您的类路径中:jackson-core,jackson-jaxrs,jackson-mapper和jackson-xc

正如其他人所指出的那样,似乎还有另一种方式。将其添加到“com.sun.jersey.config.property.packages”参数(如果使用tomcat和web.xml):“org.codehaus.jackson.jaxrs”,如下所示:

<init-param>
  <param-name>com.sun.jersey.config.property.packages</param-name>
  <param-value>org.codehaus.jackson.jaxrs</param- value>
</init-param>

执行此操作还需要在类路径中使用相同的jackson jar

答案 6 :(得分:3)

Jersey 2.0使用MOXy和Jackson提供对JSON的支持。

如果类路径中存在JAR并且可以使用功能启用Jackson支持,则默认启用MOXy支持。这在“泽西2.0用户指南”章节中有关JSON绑定的详细解释:

https://jersey.java.net/documentation/latest/media.html#json

要在不需要配置的情况下添加MOXy支持,请将以下依赖项添加到maven pom.xml

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-moxy</artifactId>
    <version>2.6</version>
</dependency>

答案 7 :(得分:2)

我是新手,但是在将jackson-all-1.9.0.jar添加到类路径后我能够使用POJO。

答案 8 :(得分:1)

以下对我有用。我在Tomcat6上运行Apache Felix(OSGi)使用Jersey 2.7 with Jackson

public class MyApplication extends ResourceConfig {

    public MyApplication() {
        super(JacksonFeature.class);
        // point to packages containing your resources
        packages(getClass().getPackage().getName());
    }
}

然后,在web.xml(或者在我的情况下,只是Hashtable),您可以指定javax.ws.rs.Application,如此

<init-param>
    <param-name>javax.ws.rs.Application</param-name>
    <param-value><MyApplication.class.getName()></param-value>
</init-param>

无需指定com.sun.jersey.config.property.pacakgescom.sun.jersey.api.json.POJOMappingFeature

确保您指定依赖

<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.7</version>
</dependency>

答案 9 :(得分:1)

jersey-json依赖项移到pom.xml的顶部为我解决了这个问题。

<dependencies>
  <dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.18.1</version>
  </dependency>

  <!-- other dependencies -->

</dependencies>

答案 10 :(得分:0)

这适用于泽西岛2.30:

System.err中:

pom.xml

<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-jackson</artifactId> <version>2.30</version> </dependency> 中:

WEB-INF/web.xml