【问题标题】:JsonView not working correctly with SpringJsonView 无法与 Spring 一起正常工作
【发布时间】:2016-04-11 11:10:41
【问题描述】:

我正在使用 Spring boot 来创建一个 restful api 服务。一切正常,除了我无法指定要以 JSON 形式返回的数据。

我想要的是获得不带“内容”字段的输出(在我的情况下用于存储对象)。

Spring 版本是 4.2.5

这就是为什么我定义了 3 级视图(Internal 是在数据库中获取/设置对象时使用的视图,Public 是要输出到客户端的最少数据):

public class EntityVisibility {
    public static class Public { }
    public static class Detailed extends Public { }
    public static class Internal extends Detailed { }
}

我的控制器:

@RestController
@RequestMapping("/api/photos")
public class PhotoController extends BaseController {

    @JsonView(EntityVisibility.Public.class)
    @RequestMapping(value="/load", method= RequestMethod.GET)
    public Response<Photo> loadFromUrl(@RequestParam("url") String urlAddress) {

        Photo photo = ...; // create photo object

        return new Response<>(photo);
    }
}

在我看来,@JsonView(EntityVisibility.Public.class) 现在正在工作。

响应类(仅相关部分):

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Response<T> {

private T result;

    public Response(T response) {
        result = response;
    }


}

我的照片类(相关部分):

public class Photo extends Entity {

    @JsonIgnore
    protected byte[] content;

    @JsonView(EntityVisibility.Public.class)
    private Date modified;

    @JsonProperty("content")
    @JsonView(EntityVisibility.Internal.class)
    public void setB64content(String b64content) {
        this.content = (b64content == null) ? null : Base64.decode(b64content.getBytes());
    }

    public String getB64content() {

        try {
            return (content.length == 0) ? null : new String(Base64.encode(content), "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    public byte[] getContent() {
        return content;
    }

    public void setContent(byte[] content) {
        this.content = content;
    }

}

实体类(相关部分):

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Entity {

}

我得到了什么:

{"success":true,"result":{"mime_type":"image/png","content":"SOME_CONTENT_HERE"}}

预期结果:

{"success":true,"result":{"mime_type":"image/png"}}

非常感谢任何帮助!

== 编辑 ==

我创建了新的非常简单的设置,但它仍然不适合我:

@RestController 中的方法:

@JsonView(EntityVisibility.Public.class)
@RequestMapping(value="/test", method= RequestMethod.GET)
public Response<TestObject> testMethos() {

    TestObject testObject = new TestObject();
    testObject.setTest1("test1");
    testObject.setTest2("test2");
    testObject.setTest3("test3");

    return new Response<>(testObject);
}

测试类:

public class TestObject {

    @JsonView(EntityVisibility.Public.class)
    private String test1;

    @JsonView(EntityVisibility.Detailed.class)
    private String test2;

    @JsonView(EntityVisibility.Internal.class)
    private String test3;

    @JsonIgnore
    private String test4;


    public String getTest1() {
        return test1;
    }

    public void setTest1(String test1) {
        this.test1 = test1;
    }

    public String getTest2() {
        return test2;
    }

    public void setTest2(String test2) {
        this.test2 = test2;
    }

    public String getTest3() {
        return test3;
    }

    public void setTest3(String test3) {
        this.test3 = test3;
    }

    public String getTest4() {
        return test4;
    }

    public void setTest4(String test4) {
        this.test4 = test4;
    }
}

我的 pom.xml(完整):

<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>ch.sumli</groupId>
    <artifactId>SumliCore</artifactId>
    <version>0.1</version>
    <packaging>war</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.3.RELEASE</version>
    </parent>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.couchbase.client</groupId>
            <artifactId>java-client</artifactId>
            <version>2.2.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>4.0.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>4.0.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>4.0.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.2.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.2.2.Final</version>
        </dependency>

        <dependency>
            <groupId>jmimemagic</groupId>
            <artifactId>jmimemagic</artifactId>
            <version>0.1.2</version>
        </dependency>

        <dependency>
            <groupId>org.imgscalr</groupId>
            <artifactId>imgscalr-lib</artifactId>
            <version>4.2</version>
        </dependency>

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz-jobs</artifactId>
            <version>2.2.2</version>
        </dependency>

    </dependencies>

    <properties>
        <start-class>ch.sumli.Application</start-class>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.7</java.version>
    </properties>

    <repositories>
        <repository>
            <id>couchbase</id>
            <name>couchbase repo</name>
            <url>http://files.couchbase.com/maven2</url>
            <snapshots><enabled>false</enabled></snapshots>
        </repository>
    </repositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

我仍然得到一切(@JsonIgnore 除外):

{"success":true,"result":{"test1":"test1","test2":"test2","test3":"test3"}}

【问题讨论】:

  • 您可以尝试在响应中删除@JsonInclude(JsonInclude.Include.NON_NULL) 并检查一次吗?
  • @Pavan 我试过了,但它并没有改变内容输出。它添加了很多空值: {"success":true,"error":null,"errorCode":null,"message":null,"result":{"key":"c24226c6-bfaa-4dd7-8972 -3249717e08a8","mime_type":"image/png","content":"..."}}
  • 你试过@JsonIgnore吗?
  • @Sam 我根本不想忽略它们。我使用这些属性来存储对象。我想选择性地忽略“内容”。

标签: java spring rest jackson


【解决方案1】:

在评论部分与 @kkazakov 讨论后,问题似乎出在来自不同 Jackson 库版本的 @JsonView 中:

原来,Couchbase 库里面也有 Jackson。还有包裹 名字完全不同。所以,我正在使用来自 couchbase 的 @JsonView 包,还有来自 Spring 的 Jackson。

旧帖:

我测试了您的代码,我认为它可以按预期工作。至少我看不到内容并获得所需的 json。唯一的区别是class Response&lt;T&gt; 中的@JsonView(EntityVisibility.Public.class),但我认为你也有它,因为否则你会得到空对象

这里是演示项目。您能否在您的设备上进行测试或指出不同的设置。

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonView;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import java.util.*;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    public static class EntityVisibility {
        public static class Public { }
        public static class Detailed extends Public { }
        public static class Internal extends Detailed { }
    }

    @RestController
    public static class MyRestController {

        @JsonView(EntityVisibility.Public.class)
        @RequestMapping(value="/", method= RequestMethod.GET)
        public Response<Photo> loadFromUrl() {

            Photo photo = new Photo(); // create photo object
            photo.setB64content("dfgsdfgsdfg");
            photo.setMime_type("image/png");
            System.out.println(photo);
            return new Response<>(photo);
        }
    }


    @JsonInclude(JsonInclude.Include.NON_NULL)
    public static class Response<T> {
        @JsonView(EntityVisibility.Public.class)
        private T result;

        @JsonView(EntityVisibility.Public.class)
        private boolean success = true;

        @JsonView(EntityVisibility.Public.class)
        private Object error;

        @JsonView(EntityVisibility.Public.class)
        private String errorCode;

        @JsonView(EntityVisibility.Public.class)
        private String message;

        public T getResult() {
            return result;
        }

        public void setResult(T result) {
            this.result = result;
        }

        public Response(T response) {
            result = response;
        }

        public boolean isSuccess() {
            return success;
        }

        public void setSuccess(boolean success) {
            this.success = success;
        }

        public Object getError() {
            return error;
        }

        public void setError(Object error) {
            this.error = error;
        }

        public String getErrorCode() {
            return errorCode;
        }

        public void setErrorCode(String errorCode) {
            this.errorCode = errorCode;
        }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }

    public static class Photo extends Entity {

        @JsonIgnore
        protected byte[] content;

        @JsonView(EntityVisibility.Public.class)
        private Date modified;

        @JsonView(EntityVisibility.Public.class)
        private String mime_type;

        @JsonProperty("content")
        @JsonView(EntityVisibility.Internal.class)
        public void setB64content(String b64content) {
            this.content = (b64content == null) ? null : b64content.getBytes();
        }

        public String getB64content() {
            return (content.length == 0) ? null : Base64.encode(content);
        }

        public byte[] getContent() {
            return content;
        }

        public void setContent(byte[] content) {
            this.content = content;
        }

        public Date getModified() {
            return modified;
        }

        public void setModified(Date modified) {
            this.modified = modified;
        }

        public String getMime_type() {
            return mime_type;
        }

        public void setMime_type(String mime_type) {
            this.mime_type = mime_type;
        }

        @Override
        public String toString() {
            return "Photo{" +
                    "content=" + Arrays.toString(content) +
                    ", modified=" + modified +
                    '}';
        }
    }

    @JsonInclude(JsonInclude.Include.NON_NULL)
    public static class Entity {

    }
}

127.0.0.1:8080 上的结果是:

{
  "result": {
    "mime_type": "image/png"
  },
  "success": true
}

【讨论】:

  • 感谢您的详细回复。但是,我这边肯定有什么根本性的问题。我在响应类中没有@JsonView(EntityVisibility.Public.class),但我仍然可以看到所有内容。
  • 我已经用新信息更新了初始帖子,包括 pom.xml 文件,但它仍然不适合我。我真的不知道发生了什么。控制台中没有错误。
  • @kkazakov hm,这很奇怪,因为它仍然适用于我的设置:github.com/varren/spring-jackson-JsonView 这是演示。我所做的唯一区别是从 tomcat 依赖项中删除 &lt;scope&gt;provided&lt;/scope&gt; 以便它可以运行。我还添加了基本的WebSecurity 配置来抑制/test 的安全检查,我认为安全部分不会对此产生影响。并且仍然必须在响应类中使用@JsonView(EntityVisibility.Public.class)
  • 谢谢,您的示例帮助我缩小了无效范围。原因是 BaseController 类(我在 PhotoController 中扩展的)也应该用@RestController 注释。一旦我这样做了,内容就会正确显示。我在第一次制作 TestController 而不扩展 BaseController 时缩小了范围,这很有效。能否请您更新答案,我会接受,所以如果其他人有这些问题,他们可以立即看到。
  • @kkazakov 很高兴听到你解决了这个问题。我对帖子进行了更改。但由于某些奇怪的原因,我仍然无法重现问题。空BaseController对我没有影响)你应该在那里有一些非常特别的东西;p
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-14
  • 2020-08-19
  • 2013-02-06
  • 2019-02-02
  • 2021-10-15
  • 2016-07-05
相关资源
最近更新 更多