JAX-RS(Genson + 球衣):对象未转换为 json

JAX-RS (Genson + jersey) : Object Not converted to json

我有一个在 tomcat 上运行的示例 rest 应用程序。

回复时 - ActionError 类型的对象作为 json 字符串发送到客户端。

ActionError 将传递给客户端一个

  1. ArrayStrings2
  2. ArrayFieldError
  3. 任意Objectpayload(定义为通用类型)。

在我的测试中,我通过 payload 类型的对象 Employee

通过上述安排 - 一切正常。我得到的结果如下:

{"actionErrors":["everything is ok"],"fieldErrors":null,"payload":{"empName":"Jony","empNo":"E3","position":"Manager"}}

但是,如果我去掉FieldErrorArray(private ArrayList<FieldError> fieldErrors;)部分, 所以 - ActionError 现在只包含:

1.ArrayStrings

2.Object payload

然后奇怪的是 payload 没有正确序列化 我得到:

{"actionErrors":["everything is ok"],"payload":"com.mycompany.mavenwebproject.model.Employee@41a8e0d9"}

这不会是什么原因造成的?关于如何修复它有什么想法吗?

谢谢。

以下是 class 定义:

ActionError.java

@XmlRootElement(name = "actionError")
@XmlAccessorType(XmlAccessType.FIELD)
public class ActionError<T> {
   private ArrayList<String> actionErrors;
   private ArrayList<FieldError> fieldErrors;
   private T payload;

    /**
     * @return the actionErrors
     */
    public ArrayList<String> getActionErrors() {
        return actionErrors;
    }

    /**
     * @param actionErrors the actionErrors to set
     */
    public void setActionErrors(ArrayList<String> actionErrors) {
        this.actionErrors = actionErrors;
    }

    /**
     * @return the fieldErrors
     */
    public ArrayList<FieldError> getFieldErrors() {
        return fieldErrors;
    }

    /**
     * @param fieldErrors the fieldErrors to set
     */
    public void setFieldErrors(ArrayList<FieldError> fieldErrors) {
        this.fieldErrors = fieldErrors;
    }

    public void addFieldError(String fieldName,String errorMessage){
         if (this.fieldErrors==null)
             this.fieldErrors = new ArrayList<>();
         this.fieldErrors.add(new FieldError(fieldName, errorMessage));
    }

    public void addActionError(String errorMessage){
         if (this.actionErrors==null)
             this.actionErrors = new ArrayList<>();
         this.actionErrors.add(errorMessage);
    }

    public boolean hasErrors(){
      return (fieldErrors!=null && !fieldErrors.isEmpty()) || (actionErrors!=null && !actionErrors.isEmpty());
    }

    /**
     * @return the payload
     */
    public T getPayload() {
        return payload;
    }

    /**
     * @param payload the payload to set
     * @return 
     */
    public ActionError setPayload(T payload) { //Class<T> payloadClass
        this.payload = payload;
        return this;
    }
}

FieldError.java

@XmlRootElement(name = "fieldError")
@XmlAccessorType(XmlAccessType.FIELD)
public class FieldError {
    private String fieldName;
    private String fieldError;

    /**
     * @return the fieldName
     */
    public String getFieldName() {
        return fieldName;
    }

    /**
     * @param fieldName the fieldName to set
     */
    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }

    /**
     * @return the fieldError
     */
    public String getFieldError() {
        return fieldError;
    }

    /**
     * @param fieldError the fieldError to set
     */
    public void setFieldError(String fieldError) {
        this.fieldError = fieldError;
    }

    public FieldError(String fieldName, String fieldError) {
        this.fieldName = fieldName;
        this.fieldError = fieldError;
    }


}

Employee.java

@XmlRootElement(name = "employee")
@XmlAccessorType(XmlAccessType.FIELD)
public class Employee {

    private String empNo;
    private String empName;
    private String position;

    // This default constructor is required if there are other constructors.
    public Employee() {

    }

    public Employee(String empNo, String empName, String position) {
        this.empNo = empNo;
        this.empName = empName;
        this.position = position;
    }

    public String getEmpNo() {
        return empNo;
    }

    public void setEmpNo(String empNo) {
        this.empNo = empNo;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public String getPosition() {
        return position;
    }

    public void setPosition(String position) {
        this.position = position;
    }

}

我设法 运行 在 Glassfish 4.1.1 和 Tomcat 8 上使用以下依赖项:

Tomcat 8

<dependency>
    <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.bundles/jaxrs-ri -->
        <groupId>org.glassfish.jersey.bundles</groupId>
        <artifactId>jaxrs-ri</artifactId>
        <version>2.12</version>
        <type>zip</type>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.owlike/genson -->
    <dependency>
        <groupId>com.owlike</groupId>
        <artifactId>genson</artifactId>
        <version>1.4</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.2.7</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
    <dependency>
        <groupId>javax.ws.rs</groupId>
        <artifactId>javax.ws.rs-api</artifactId>
        <version>2.0.1</version>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-web-api</artifactId>
        <version>7.0</version>
        <scope>provided</scope>
    </dependency>

玻璃鱼 4.1.1

 <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
  <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.bundles/jaxrs-ri -->      

        <dependency>
            <groupId>org.glassfish.jersey.bundles</groupId>
            <artifactId>jaxrs-ri</artifactId>
            <version>2.12</version>    
            <scope>provided</scope>
            <type>zip</type>
        </dependency>

        <!-- https://mvnrepository.com/artifact/com.owlike/genson -->

         <dependency>
            <groupId>com.owlike</groupId>
            <artifactId>genson</artifactId>
            <version>1.4</version>
        </dependency>


        <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2.7</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>2.0.1</version>
        </dependency>
       <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>

我的 web.xml 也有以下条目:

<servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
             <param-name>jersey.config.server.provider.packages</param-name>
             <param-value>com.mycompany.mavenwebproject</param-value>
        </init-param>
        <init-param>
        <param-name>jersey.config.server.provider.classnames</param-name>
        <param-value>org.glassfish.jersey.jackson.JacksonFeature</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

Also To 运行 on Glassfish 3.1.2 Jersey 1.x 必须用,不需要Genson。

因此,pom.xml 依赖项如下所示:

<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-server</artifactId>
    <version>1.8</version>
</dependency>

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

   <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
</dependency>

web.xml 条目:

<servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.mycompany.mavenwebproject</param-value>
        </init-param>
        <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>
    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

编辑 1

为了放弃在 glassfish 4.1.1 上使用 genson,应该将缺少的库 jackson-module-jaxb-annotations-2.5.4.jar 添加到 Glassfish 模块目录中。 否则

java.lang.ClassNotFoundException:
com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector not found by com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider

会被抛出。 但是,如果添加了上述 jar,则 Glassfish 的 pom 可能如下所示:

Glassfish 4.1.1(修复了缺少的库错误)

<dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.3.2</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
  <!-- https://mvnrepository.com/artifact/org.glassfish.jersey.bundles/jaxrs-ri -->      

        <dependency>
            <groupId>org.glassfish.jersey.bundles</groupId>
            <artifactId>jaxrs-ri</artifactId>
            <version>2.12</version>    
            <scope>provided</scope>
            <type>zip</type>
        </dependency>


        <!-- https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2.7</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.ws.rs/javax.ws.rs-api -->
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>javax.ws.rs-api</artifactId>
            <version>2.0.1</version>
        </dependency>

        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

编辑 2.

如果想在 Glassfish 3.1.2 和 jersey 1 上使用 jackson 2,则执行以下操作 配置有序

pom.xml

  <dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>6.0</version>
            <scope>provided</scope>
        </dependency>
  <dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-server</artifactId>
    <version>1.8</version>
</dependency>

<!-- removed to use jackson 2 not 1
<dependency>
    <groupId>com.sun.jersey</groupId>
    <artifactId>jersey-json</artifactId>
    <version>1.8</version>
</dependency>
-->

<!-- jackson 2 json provider  -->
<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-json-provider</artifactId>
    <version>2.2.3</version>
</dependency>

<!-- jackson 2 xml provider 
<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-xml-provider</artifactId>
    <version>2.2.3</version>
</dependency>
-->
<dependency>
    <groupId>com.sun.jersey.contribs</groupId>
    <artifactId>jersey-multipart</artifactId>
    <version>1.8</version>
</dependency>
   <dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version>6.0</version>
    <scope>provided</scope>
    </dependency>
      <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.3.2</version> <!-- unlike jersey 2 on glassfish 4.1.1 here it is not provided! -->
       </dependency>

    </dependencies>

web.xml 变为

<servlet>
        <servlet-name>jersey-serlvet</servlet-name>
        <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>
                                     com.mycompany.mavenwebproject
                                    <!--
                                    Jackson 2.x JAX-RS @Providers
                                    -->
                                     com.fasterxml.jackson.jaxrs.json <!--JSON -->
                                     <!-- com.fasterxml.jackson.jaxrs.xml  -->  <!-- XML -->
                        </param-value>
        </init-param>
        <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>
    <servlet-mapping>
        <servlet-name>jersey-serlvet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>