【问题标题】:How do I use the Jersey JSON POJO support?如何使用 Jersey JSON POJO 支持?
【发布时间】:2011-07-06 21:31:24
【问题描述】:

我有一个对象,我想在 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
...

我要服务的类并不复杂,它所拥有的只是一些公共的 final 字段和一个设置所有这些字段的构造函数。这些字段都是字符串、原语、与此类似的类或其列表(我尝试使用普通列表而不是通用 Lists,但无济于事)。有谁知道给了什么?谢谢!

Java EE 6

球衣 1.1.5

玻璃鱼 3.0.1

【问题讨论】:

    标签: java json rest jakarta-ee jersey


    【解决方案1】:

    为什么要使用 final 字段? 我正在使用球衣,我有一些 JAXB 对象/pojos,我所要做的只是用 @Produces("application/json") 注释我的资源方法,它开箱即用。我不必弄乱 web.xml。只需确保您的 pojo 注释正确。

    这是一个简单的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;
        }
    
    
    }
    

    【讨论】:

    • 谢谢!我已经能够让它与 JAXB 一起工作,但我专门寻找 Jersey POJO 写作,而不是 JAXB 写作。有最终字段会干扰吗?我有 final 字段,因为它们代表对象的不可变属性。
    【解决方案2】:

    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 后,Jersey 应该有助于在您的资源中进行编组:

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

    【讨论】:

    • 谢谢!看起来我误解了 Jersey JSON/POJO 的工作原理。
    • 仅供记录 - 此答案不再适用于泽西岛 v1.18。您不需要编写自己的 MessageBodyWriter 并且您的 @GET 方法的返回类型可以是 POJO 对象。
    • 仅供参考,如果使用 maven,这将为您提供:&lt;dependency&gt; &lt;groupId&gt;com.sun.jersey&lt;/groupId&gt; &lt;artifactId&gt;jersey-json&lt;/artifactId&gt; &lt;version&gt;1.8&lt;/version&gt; &lt;/dependency&gt;
    • 第二个@Nilzor - 很好的问题,但这不再是最佳答案。
    • 是的,强调一下,如果您今天遇到此问题,您的问题很可能是类路径问题,正如此处其他答案所述。
    【解决方案3】:

    我遵循了here 的说明,其中显示了如何使用 Jersey 和 Jackson POJO(而不是 JAXB)。它也适用于 Jersey 1.12。

    【讨论】:

    • 嘿 smiths,虽然它的回答很关心 1.12 版。在 jersey-json v1.12 中没有 POJOMappingFeature 类。我们是否需要添加任何额外的 jar 或需要更改 Jersey 最新版本的配置。在官方球衣网站 (jersey.java.net/nonav/documentation/latest/json.html) 上,文档似乎很旧。请指导我,因为我不想将不必要的 JAXB 注释 @XMLRootElement 添加到我的 POJO 中。谢谢。
    • 这是我的解决方案。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

      如果您想使用 JAXB 注释,可以使用 @XmlRootElement(请参阅其他答案)。

      但是,如果您更喜欢纯 POJO 映射,则必须执行以下操作(遗憾的是它没有写在文档中):

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

      【讨论】:

      • 很好...我完全忘记将@XmlRootElement 添加到我项目中的一个类中。谢谢!
      • 天哪,谢谢。神奇的额外扫描包为我修复了它。我已经关注了所有其他有关类路径和手动提供程序注册的相关帖子。再次感谢。
      【解决方案6】:

      您可能已经想通了,但您需要做的就是将这些 jackson jar 添加到您的类路径中: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

      【讨论】:

        【解决方案7】:

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

        如果 JAR 存在于类路径中,则默认启用 MOXy 支持,并且可以使用功能启用 Jackson 支持。这在 Jersey 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>
        

        【讨论】:

          【解决方案8】:

          这是为我做的 - Jersey 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>
          

          【讨论】:

          • 这对我有用,只有一个更正参数名称必须是 com.sun.jersey.config.property.packages
          • 我从Maven 添加了jersey-media-json-jackson。有用。非常感谢。
          • @Pavlonator,如果您使用的是 JAXRS-2.0,param-namejersey.config.server.provider.packages,如果您仍在使用 1.x,param-name 是 com.sun.jersey.config。 property.packages
          【解决方案9】:

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

          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>
          

          【讨论】:

            【解决方案10】:

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

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

            【讨论】:

              【解决方案11】:

              这在 Jersey 2.30 中有效:

              pom.xml:

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

              WEB-INF/web.xml:

              <servlet>
                <servlet-name>My Jersey REST Service</servlet-name>
                <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
                <load-on-startup>1</load-on-startup>
                <!-- ATTENTION: Use Jackson for JSON: -->
                <init-param>
                  <param-name>jersey.config.server.provider.classnames</param-name>
                  <param-value>org.glassfish.jersey.jackson.JacksonFeature</param-value>
                </init-param>
                <!-- ... -->
                <init-param>
                  <param-name>jersey.config.server.provider.packages</param-name>
                  <param-value>com.example.myapp</param-value>
                </init-param>
              </servlet>
              

              【讨论】:

                猜你喜欢
                • 2015-12-01
                • 2015-12-19
                • 1970-01-01
                • 1970-01-01
                • 2013-07-04
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多