Home > Enterprise >  Disable validation annotation when filtering with Jackson @JsonView
Disable validation annotation when filtering with Jackson @JsonView

Time:10-13

I have the same form that displays more or less fields depending on the user's role. So I use @JsonView to hide/ignore the fields that are not related to the current user's role. But the validation is still enabled and the @NotNull rule is triggered.

@JsonView({View.Admin.class, View.Tech.class})
@NotNull
private String name;

I would like to find a way to enable or disable some validation annotations for example when the user's role is not administrator.

Is it possible to use these view (View.Admin.class / View.Tech.class) as a group for validation please?

CodePudding user response:

We can do this!

(no spring-security, for simplicity) just:

  1. start.spring.io web validation.

  2. With ("trick" is to use interfaces instead of classes!):

    class View {
    
         interface Public {
         }
    
         interface User extends Public {
         }
    
         interface Admin extends User {
         }
     }
    
  3. And (referring to the same interfaces as @JsonView and as "validation group"):

    class MyDto {
         // visible by/validated for all:
         @NotNull(groups = View.Public.class)
         @JsonView(View.Public.class)
         private String foo;
         // visible by/validated for "User"
         @JsonView(View.User.class)
         @NotNull(groups = View.User.class)
         private String bar;
         // visible by/validated for "Admin" (and "User")
         @JsonView(View.Admin.class)
         @NotNull(groups = View.Admin.class)
         private String baz;
         // getter   setter !! (hashcode, equals..)
    
  4. We can try:

     @RestController
     class DemoController {
    
         @PostMapping("/foo")
         @JsonView(View.Public.class)
         public MyDto foo(
             @Validated(View.Public.class)
             @RequestBody MyDto dto) {
             return dto;
         }
    
         @PostMapping("/bar")
         @JsonView(View.User.class)
         public MyDto bar(
             @Validated(View.User.class) 
             @RequestBody MyDto dto) {
             return dto;
         }
    
         @PostMapping("/baz")
         @JsonView(View.Admin.class)
         public MyDto baz(
             @Validated(View.Admin.class)
             @RequestBody MyDto dto) {
             return dto;
         }
     }
    

Test

package com.example.jsonviewsmeetsvalidationgroups;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class DemoControllerTest {

    @Autowired
    MockMvc mvc;

    @Test
    void testPublicGood() throws Exception {
        mvc.perform(
                post("/foo")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content("{\"foo\":\"Test1\"}"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.foo").value("Test1"));
    }

    @Test
    void testPublicInvalid1() throws Exception {
        mvc.perform(
                post("/foo")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content("{}")
            )
            .andExpect(status().isBadRequest());
    }

    @Test
    void testUserGood() throws Exception {
        mvc.perform(post("/bar")
                .contentType(MediaType.APPLICATION_JSON)
                .content("{\"foo\":\"Test1\", \"bar\":\"Test2\"}"))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.foo").value("Test1"))
                .andExpect(jsonPath("$.bar").value("Test2"));
    }

    @Test
    void testUserInvalid1() throws Exception {
        mvc.perform(post("/bar")
                .contentType(MediaType.APPLICATION_JSON)
                .content("{}"))
                .andExpect(status().isBadRequest());
    }

    @Test
    void testUserInvalid2() throws Exception {
        mvc.perform(post("/bar")
                .contentType(MediaType.APPLICATION_JSON)
                .content("{\"foo\":\"Test1\"}")
        ).andExpect(status().isBadRequest());
    }

    // analogous for "/baz" / Admin ... 
}

CodePudding user response:

use @JsonIgnore may help you to achieve,because it will ignore the column and validation annotation as well

  • Related