JsonView not working correctly with Spring

你说的曾经没有我的故事 提交于 2021-02-07 14:32:36

问题


I'm using Spring boot to create a restful api service. Everything works correctly, except that I cannot specify which data to be returned as JSON.

What I want is to get the output without the field "content" ( which in my case is used for storing the object ).

Spring version is 4.2.5

That's why I've defined 3 levels of views ( Internal being the one to be used when getting / setting object in the database, Public is the minimal data to be output to client ):

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

My controller:

@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);
    }
}

To me, it looks that @JsonView(EntityVisibility.Public.class) is now working.

Response class (only relevant parts):

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

private T result;

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


}

My Photo class (relevant parts):

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;
    }

}

Entity class (relevant parts):

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

}

What I'm getting:

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

Expected result:

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

Any help is greatly appreciated!

== EDIT ==

I've created new very simple setup, but it's still not working for me:

Method in the @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);
}

The test class:

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;
    }
}

My pom.xml (full):

<?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>

And I'm still getting everything ( except for @JsonIgnore ):

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

回答1:


After comment section discussion with @kkazakov it seems that the problem is in @JsonView from different Jackson library version:

Turns out, Couchbase library also has Jackson inside. And the package name is completely different. So, I was using @JsonView from couchbase package, and Jackson from Spring.

Old post:

I tested your code and i think it works as intended for me. At least i can't see content and get desired json. The only difference is @JsonView(EntityVisibility.Public.class) in class Response<T>, but i think you also have it, because you will be getting empty object otherwise

Here is demo project. Can you test in on your device or point me to different setup.

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 {

    }
}

Result on 127.0.0.1:8080 is:

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


来源:https://stackoverflow.com/questions/36547042/jsonview-not-working-correctly-with-spring

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!