【问题标题】:Jersey 2 + Jackson Annotation / @JsonIgnoreJersey 2 + Jackson 注释/@JsonIgnore
【发布时间】:2018-10-13 08:22:23
【问题描述】:

编辑:现在更具体地说,我注意到我想在下面使用两个依赖项的冲突:

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

基本上,我试图忽略一个属性 (@JsonIgnore),但我的 Jackson 注释都不起作用。甚至是@JsonProperty。我尝试在 getter 和 setter 方法中添加 @JsonIgnore,但行为相同。

我也尝试过关注官方文档,尝试了不同的库

  • 导入 org.codehaus.jackson.annotate.JsonIgnore; (相同的行为)
  • 导入com.fasterxml.jackson.annotation.JsonIgnore; (相同的行为)

我看到类似的帖子,例如#12595351

我来自控制器的响应,不应显示已撤销。属性,但我得到了这个响应:

实际反应

{
    "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImlzcyI6ImpvaG4uZG9lQGV4YW1wbGUuY29tIiwiaWF0IjoxNTI1MzI1Nzk1LCJleHAiOjE1MjUzMzI5OTV9.uri3pRwXQHHG09F-wM40qfuRMRVu_WBK3HlfquGvwYc",
    "expiresAt": "2018-05-03T07:36:35.087Z[UTC]",
    "expiresIn": 7199,
    "issuedAt": "2018-05-03T05:36:35.087Z[UTC]",
    "refreshToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImlzcyI6ImpvaG4uZG9lQGV4YW1wbGUuY29tIiwiaWF0IjoxNTI1MzI1Nzk1LCJleHAiOjE1MjU5MzA1OTV9.xj2oytAVwiAIR8U2upJkPH_BdORuJUNbiicvuvGFz0w",
    "revoked": false,
    "type": "Bearer"
}

预期响应

{
    "accessToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImlzcyI6ImpvaG4uZG9lQGV4YW1wbGUuY29tIiwiaWF0IjoxNTI1MzI1Nzk1LCJleHAiOjE1MjUzMzI5OTV9.uri3pRwXQHHG09F-wM40qfuRMRVu_WBK3HlfquGvwYc",
    "expiresAt": "2018-05-03T07:36:35.087Z[UTC]",
    "expiresIn": 7199,
    "issuedAt": "2018-05-03T05:36:35.087Z[UTC]",
    "refreshToken": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJqb2huLmRvZUBleGFtcGxlLmNvbSIsImlzcyI6ImpvaG4uZG9lQGV4YW1wbGUuY29tIiwiaWF0IjoxNTI1MzI1Nzk1LCJleHAiOjE1MjU5MzA1OTV9.xj2oytAVwiAIR8U2upJkPH_BdORuJUNbiicvuvGFz0w",
    "type": "Bearer"
}

pom.xml(使用 Maven)

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

<modelVersion>4.0.0</modelVersion>

<groupId>com.wedhany.fimper</groupId>
<artifactId>fimper</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>fimper</name>

<build>
    <finalName>fimper</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>2.5.1</version>
            <inherited>true</inherited>
            <configuration>
                <source>8</source>
                <target>8</target>
            </configuration>
        </plugin>
    </plugins>
</build>

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.glassfish.jersey</groupId>
            <artifactId>jersey-bom</artifactId>
            <version>${jersey.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.8.2</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>de.mkammerer</groupId>
        <artifactId>argon2-jvm</artifactId>
        <version>2.4</version>
    </dependency>
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.0</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.11</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.7</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-dbcp</artifactId>
        <version>9.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.flywaydb</groupId>
        <artifactId>flyway-core</artifactId>
        <version>5.0.7</version>
    </dependency>
    <dependency>
        <groupId>org.modelmapper</groupId>
        <artifactId>modelmapper</artifactId>
        <version>1.1.0</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.containers</groupId>
        <artifactId>jersey-container-servlet</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.inject</groupId>
        <artifactId>jersey-hk2</artifactId>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-binding</artifactId>
        <version>2.27</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-json-jackson</artifactId>
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.ext</groupId>
        <artifactId>jersey-spring4</artifactId>
        <version>2.27</version>
    </dependency>
    <dependency>
        <groupId>org.glassfish.jersey.test-framework.providers</groupId>
        <artifactId>jersey-test-framework-provider-jdk-http</artifactId>
        <version>${jersey.version}</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>5.2.17.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.9.Final</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${springframework.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${springframework.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${springframework.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${springframework.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${springframework.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${springframework.version}</version>
    </dependency>
</dependencies>

<profiles>
    <profile>
        <id>Development</id>
        <dependencies>
            <dependency>
                <groupId>com.github.blocoio</groupId>
                <artifactId>faker</artifactId>
                <version>1.2.7</version>
            </dependency>
        </dependencies>
    </profile>
</profiles>

<properties>
    <jersey.version>2.27</jersey.version>
    <springframework.version>4.3.16.RELEASE</springframework.version>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

Token.java(我的模型)

package com.wedhany.models;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.wedhany.models.enums.token.GrantType;
import com.wedhany.models.enums.token.Type;

import java.util.Date;

public class Token {

/**
 * Attributes
 */
private String accessToken;
private String refreshToken;

@JsonIgnore
private boolean revoked;

@JsonProperty("expires_at")
private Date expiresAt;
private Date issuedAt;

private GrantType grantType;
private Type type;

private User user;

/**
 * @return Token TTL in seconds.
 */
public long getExpiresIn() {
    return this.expiresAt.getTime() < new Date().getTime()
            ? 0
            : (this.expiresAt.getTime() - new Date().getTime()) / 1000;
}

/**
 * @return Token that will grant authentication and authorization.
 */
public String getAccessToken() {
    return accessToken;
}

/**
 * @param accessToken Token string.
 */
public void setAccessToken(String accessToken) {
    this.accessToken = accessToken;
}

/**
 * @return Token used to request a new token.
 */
public String getRefreshToken() {
    return refreshToken;
}

/**
 * @return Invalid token if true.
 */
public boolean isRevoked() {
    return revoked;
}

/**
 * @param revoked True for invalid.
 */
public void setRevoked(boolean revoked) {
    this.revoked = revoked;
}

/**
 * @param refreshToken Refresh token.
 */
public void setRefreshToken(String refreshToken) {
    this.refreshToken = refreshToken;
}

/**
 * @return Token's expiration date.
 */
public Date getExpiresAt() {
    return expiresAt;
}

/**
 * @param expiresAt Token's expiration date.
 */
public void setExpiresAt(Date expiresAt) {
    this.expiresAt = expiresAt;
}

/**
 * @return Date where the token was requested.
 */
public Date getIssuedAt() {
    return issuedAt;
}

/**
 * @param issuedAt Date where the token was requested.
 */
public void setIssuedAt(Date issuedAt) {
    this.issuedAt = issuedAt;
}

/**
 * @return Type of the token.
 */
public Type getType() {
    return type;
}

/**
 * @param type Type of the token.
 */
public void setType(Type type) {
    this.type = type;
}

/**
 * @return How the token was claimed.
 */
public GrantType getGrantType() {
    return grantType;
}

/**
 * @param grantType Set token type of grant.
 */
public void setGrantType(GrantType grantType) {
    this.grantType = grantType;
}

/**
 * @return Owner of the token
 */
public User getUser() {
    return user;
}

/**
 * @param user Token's owner.
 */
public void setUser(User user) {
        this.user = user;
    }
}

身份验证控制器

package com.wedhany.controllers;

import com.wedhany.exceptions.AuthorizationException;
import com.wedhany.models.Token;
import com.wedhany.models.User;
import com.wedhany.services.AuthenticationService;
import org.springframework.beans.factory.annotation.Autowired;

import javax.security.sasl.AuthenticationException;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

@Path("auth")
public class AuthenticationController {

@Autowired
private AuthenticationService authenticationService;

@POST
@Path("login")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response login(User user, @HeaderParam("user-agent") String userAgent) throws Exception {
    try {
        // Authenticate the user using the credentials provided
        this.authenticationService.authenticate(user.getEmail(), user.getPassword());

        // Issue a token for the user
        Token token = this.authenticationService.issueToken(user.getEmail(), userAgent);

        // Return the token on the response
        return Response.ok(token).build();

    } catch (AuthorizationException e) {
        return Response.status(Response.Status.UNAUTHORIZED).build();
    } catch (AuthenticationException e) {
        return Response.status(Response.Status.FORBIDDEN).build();
    }
}

@POST
@Path("refresh")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response refresh(Token token, @HeaderParam("user-agent") String userAgent) throws AuthenticationException {
    return Response.status(Response.Status.CREATED)
            .entity(this.authenticationService.refresh(token.getRefreshToken(), userAgent))
            .build();
}

@POST
@Path("register")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response register(User user) {
    user = authenticationService.save(user);

    return Response.status(Response.Status.CREATED)
            .entity(user)
            .build();
}
}

【问题讨论】:

  • 我尝试在课堂上使用@JsonIgnoreProperties。同样的事情......
  • 在属性上添加 \@JsonIgnore,在春季与杰克逊一起在序列化/反序列化中被忽略。尝试在 bean 中的 isRevoked() 方法上添加 \@JsonIgnore。即使这不起作用,请尝试在 bean 类上添加 \@JsonIgnoreProperties("revoked") 。此外,您正在将 Jackson 1 与 Jackson 2 混合,尝试从依赖项中排除 Jackson 1(或 2)
  • @HemantPatel 我注意到如果我删除 jersey-media-json-binding 按预期工作。

标签: java spring-mvc jersey


【解决方案1】:

这对我有用,我的 pom.xml 中有这些库:

        <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-json-jackson</artifactId>
            <version>${org.glassfish.jersey.core.version}</version>
            <scope>provided</scope>
        </dependency>


        <!-- ************** Jackson XML and JSON API ************************* -->          
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson-version}</version>
        </dependency>   

       <dependency>
            <groupId>org.glassfish.jersey.media</groupId>
            <artifactId>jersey-media-moxy</artifactId>
            <version>${org.glassfish.jersey.core.version}</version>             
            <scope>provided</scope>
        </dependency>

只需从您的类中删除该属性并添加此注释:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown=true)
public class Token {
// ... keep only the properties you want to map

这将告诉 Jackson 只绑定您在类中实际拥有的属性,而忽略 JSON 输出中可能存在的所有其他属性。

【讨论】:

  • 相同的行为。输出是一样的。我不想忽略未知,只是想让您知道,@JsonIgnoreProperties 无法正常工作,因为它们来自同一个库(com.fasterxml.jackson.annotation.JsonIgnoreProperties)。该库中没有任何注释与 jersey-media-json-binding 一起使用
【解决方案2】:

选择以下其中一项,但不能同时选择两项:

<!-- JSON-B (JSR-347) support -->
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-binding</artifactId>
    <version>2.27</version>
</dependency>
<!-- Jackson 2.x support -->
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>2.27</version>
</dependency>

Jackson 和 JSON-B 都提供 JSON 从/到 Java 绑定:


如果你想使用jersey-media-json-jackson,你应该使用Jackson annotations。例如,要忽略某个属性,请使用@JsonIgnore

如果你想使用jersey-media-json-binding,你应该使用 JSON-B annotations。例如,要忽略某个属性,请使用 @JsonbTransient


您正在使用jersey-bom,这是一个依赖管理工件,用于整合和集中管理依赖版本(实际上并未将依赖添加到项目中)。

因此您无需指定org.glassfish.jersey 工件的版本。使用以下之一(不带version):

<!-- JSON-B (JSR-347) support -->
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-binding</artifactId>
</dependency>
<!-- Jackson 2.x support -->
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
</dependency>

查看更多详情 herehere

【讨论】:

    【解决方案3】:

    我不知道您项目的整个配置,所以有人认为您可以这样做,手动创建 JSON,然后发送到响应,例如:

    ObjectMapper maper = new ObjectMapper();
    return Response.ok(maper.writer().withDefaultPrettyPrinter().writeValueAsString(tokenObject));
    

    它将像手动转换一样工作,无需使用 Jersey 的自动序列化。
    注意:这个东西是不推荐的,但它应该可以工作。

    你需要这个依赖来进行转换:

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.2.3</version>
    </dependency>
    

    【讨论】:

      【解决方案4】:

      基本上 jersey-media-json-bindingjersey-media-json-jackson 具有相似的行为。你不能同时使用两者。 jersey-media-json-jackson 不起作用的原因是因为具有更高优先级的提供者是 jersey-media-json-binding。

      【讨论】:

        【解决方案5】:

        以下代码适用于杰克逊版本 2.8.10

        import com.fasterxml.jackson.annotation.JsonIgnore;
        import com.fasterxml.jackson.core.JsonProcessingException;
        import com.fasterxml.jackson.databind.ObjectMapper;
        
        public class JsonIgnoreExample {
            private static class BeanWithIgnore {
                @JsonIgnore
                public int id;
                public String name;
        
                public BeanWithIgnore(int id, String name) {
                    this.id = id;
                    this.name = name;
                }
            }
        
            public static void main(String[] args) throws JsonProcessingException {
                BeanWithIgnore bean = new BeanWithIgnore(1, "My bean");
                String result = new ObjectMapper().writeValueAsString(bean);
                System.out.println(result); // {"name":"My bean"}
            }
        }
        

        【讨论】:

        • 如果我创建一个新项目它可以工作,我对这个特定的项目有疑问,我刚刚发现 jersey-media-json-jackson 和 jersey-media-json-binding 之间存在冲突。但我真的很想使用 jersey-media-json-binding。
        猜你喜欢
        • 2018-11-18
        • 2011-12-20
        • 1970-01-01
        • 2016-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-03
        • 1970-01-01
        相关资源
        最近更新 更多