SpringMvc @JsonView 使用方式


准確來說,@JsonView注解不是Spring的,它位於jackson-annotation包中; 作用:SpringMvc使用@ResponseBody將結果以json返回客戶端,  有些實體類的某些字段可以不被包括在JSON中;

思考了這種情況可能適用的情形:有多方調用這個接口,需要針對不同業務場景返回不同形式的JSON,但是這種情況的話 只拷貝需要的屬性 再返回也能達到目的,就當多學了一種注解、處理方式了;

一.作為 Jackson Api使用:

public class View {
    public static class UserPublic{}

    public static class UserPrivacy{}
}
public class User {
    @JsonView(View.UserPublic.class)
    public int id;

    @JsonView(View.UserPrivacy.class)
    public String name;
}

補充說明:每一個@JsonView標注在屬性上,代表該屬性在被序列化時候會被轉化,視圖名字為value指向的class;

public class User {
    @JsonView(View.UserPublic.class)
    int id;

    @JsonView(View.UserPrivacy.class)
    String name;

    public void setId(int id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }
}

public static void main(String[] args) throws JsonProcessingException {
    User user = new User();
    user.setId(1);
    user.setName("lvbb");
    ObjectMapper mapper = new ObjectMapper();
    String res1 = mapper.writerWithView(View.UserPublic.class).writeValueAsString(user);
    System.out.println(res1);
    String res2 = mapper.writerWithView(View.UserPrivacy.class).writeValueAsString(user);
    System.out.println(res2);
}

輸出結果:

image_thumb2

 

@JsonView注解沒有@Repeatable注解標注,意味着一個屬性只能標注一個@JsonView注解,  比如 View.UserPrivacy 這個Json View也需要有id字段,解決方案就是 讓 UserPrivacy 繼承 UserPublic視圖

image_thumb4

同樣的main方法查看輸出: {"id":1,"name":"lvbb"} 

 

二. 結合Spring的使用方式. (注解@JsonView的 value只能為一個)

簡單列舉個例子如下: 在@ResponseBody標注下添加  @JsonView指定要展示的JSON View即可.

    @RequestMapping("/demo2")
    @ResponseBody
    @JsonView(value = MyView.UserDetail.class)
    public User demo2(){
        User user = new User();
        user.setName("lvbinbin");
        user.setPassword("qwer0-5");
        return user;
    }

上面的代碼使用效果和下面一段是一模一樣的:

@RequestMapping(value = "/demo4")
    @ResponseBody
    public MappingJacksonValue demo4(){
        User user = new User();
        user.setName("lvbinbin");
        user.setPassword("qwer0-5");
        MappingJacksonValue mjv=new MappingJacksonValue(user);
        mjv.setSerializationView(MyView.UserDetail.class);
        return mjv;
    }

Json View  Api使用:

        User user = new User();
        user.setId(1);
        user.setName("lvbb");
        ObjectMapper mapper = new ObjectMapper();
        MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(user);
        mappingJacksonValue.setSerializationView(View.UserPrivacy.class); 
        ObjectWriter writer = mapper.writerWithView(mappingJacksonValue.getSerializationView());
        String res4= writer.writeValueAsString(mappingJacksonValue.getValue());
        System.out.println(res4);

 

當然MappingJacksonValue好像也是支持SpringMvc跨域JSONP調用的,具體不太了解以后補上.

 

同樣類似的,接收JSON請求參數使用 @RequestBody同樣可以和 @JsonView使用,這時候前台接收到參數就可以忽略指定的字段

    @RequestMapping("/demo5")
    @ResponseBody
    public String demo5(@RequestBody @JsonView(MyView.UserSimple.class) User user){
        System.out.println(user);
        return "Hello World";
    }

 

Spring底層對MappingJacksonValue以及 @JsonView 流程記錄:

MappingJackson的處理過程如下

org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter#writeInternal 有這樣一個代碼片段:

@ResponseBody的返回值類型是MappingJacksonValue類型時,會做的多一步轉換工作,取出mappingJackson的value值.

image_thumb6

 

org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor#writeWithMessageConverters

在往響應對象Response寫回結果之前, 會調用ResponseBodyAdvice接口的beforeBodyWrite方法進行切面處理,當前對象為 RequestResponseBodyAdviceChain,其持有JsonViewResponseBodyAdvice 以及JsonViewRequestBodyAdvice, 前者就是處理@ResponseBody的;

image_thumb8

JsonViewResponseBodyAdvice 直接獲取了 方法上的JsonView注解,然后調用Jackson View Api進行設置;也就是說上面提及到的兩種方式是一模一樣的.

image_thumb10

 

參考文檔:

一個關於jackson使用很全面的外文網站https://www.baeldung.com/jackson


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM