2016-04-17 8 views
3

У меня есть несколько полей в модели, которые я хочу вернуть только тогда, когда зарегистрированный пользователь имеет роль ROLE_ADMIN. Я могу использовать @JsonIgnore, но это скрывает его для всех. Как я могу заставить его скрывать динамически?Поле Deserialise JSON на основе роли пользователя

+1

http://stackoverflow.com/questions/11376304/right-way-to-write-json-deserializer-in-spring-or-extend-it .. это помогает? – ArunM

ответ

2

Для достижения этой цели вы должны использовать технологию Jackson Json Views - она ​​позволяет выбирать по-разному набор полей для последовательной сериализации. Он также поддерживается Spring

Рассмотрим у вас есть класс Model с двумя свойствами: commonField, которые должны быть доступны для всех и secretField, которые должны быть доступны только для некоторых пользователей. Вы должны создать иерархию представлений (любые классы будут работать) и указать, какое поле доступно, в котором просмотреть с помощью @JsonView аннотацию

package com.stackoverflow.jsonview; 

import com.fasterxml.jackson.annotation.JsonView; 

public class Model { 

    public static class Public {} 
    public static class Secret extends Public {} 

    @JsonView(Public.class) 
    private String commonField; 

    @JsonView(Secret.class) 
    private String secretField; 

    public Model() { 
    } 

    public Model(String commonField, String secretField) { 
     this.commonField = commonField; 
     this.secretField = secretField; 
    } 

    public String getCommonField() { 
     return commonField; 
    } 

    public void setCommonField(String commonField) { 
     this.commonField = commonField; 
    } 

    public String getSecretField() { 
     return secretField; 
    } 

    public void setSecretField(String secretField) { 
     this.secretField = secretField; 
    } 

} 

Теперь вы можете указать вид, который вы хотите использовать в бетон ObjectMapper

Я не уверен, если вы можете использовать declaratie подход, чтобы сделать весной выбрать правильный вид, основанный на роли пользователя из коробки, так что, вероятно, вам придется писать код так:

@RequestMapping("/data") 
public String getData(HttpServletRequest request) { 
    Model model = service.getModel(); 
    ObjectMapper objectMapper = new ObjectMapper(); 
    objectMapper = request.isUserInRole("ROLE_ADMIN") ? objectMapper.writerWithView(Model.Secret.class) : objectMapper.writerWithView(Model.Public.class); 
    return objectMapper.writeValueAsString(model); 
} 
+0

Я видел этот сайт, но я не мог понять, как на самом деле использовать его, чтобы делать то, что я хотел. Не могли бы вы предоставить пример кода, который скрывает определенное свойство модели? – Tometoyou

+0

@Tometoyou Я обновил свой ответ на примере - мы используем этот pproach в нашем текущем проекте, и это оказалось очень полезным и удобным – bedrin

1

Я решил это буквально целый месяц, пытаясь разного рода вещами. Я работаю с Spring 4.3.1 и загружаюсь с данными, возвращаемыми в Hal с помощью pagedrepository.

  1. расширить RepositoryRestMvcConfiguration в MyRepositoryRestMvcConfiguration и добавить @Configuration к классу, убедитесь, что ваш класс пускатель @EnableWebMvc

  2. добавить это MyRepositoryRestMvcConfiguration - расширить TypeConstrainedMappingJackson2HttpMessageConverter в MyResourceSupportHttpMessageConverter

  3. добавить это MyRepositoryRestMvcConfiguration

    @Override 
    @Bean 
    public TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter() { 
    
    ArrayList<MediaType> mediaTypes = new ArrayList<MediaType>(); 
    mediaTypes.add(MediaTypes.HAL_JSON); 
    
    if (config().useHalAsDefaultJsonMediaType()) { 
        mediaTypes.add(MediaType.APPLICATION_JSON); 
    } 
    
    int order = config().useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 10 
         : Ordered.LOWEST_PRECEDENCE - 1; 
    
    TypeConstrainedMappingJackson2HttpMessageConverter converter = new MyResourceSupportHttpMessageConverter(
         order); 
    converter.setObjectMapper(halObjectMapper()); 
    converter.setSupportedMediaTypes(mediaTypes); 
    
    converter.getObjectMapper().addMixIn(Object.class, MyFilteringMixin.class); 
    final FilterProvider myRestrictionFilterProvider = new SimpleFilterProvider() 
         .addFilter("MyFilteringMixin", new MyPropertyFilter()).setFailOnUnknownId(false); 
    converter.getObjectMapper().setFilterProvider(myRestrictionFilterProvider); 
    
    return converter; 
    } 
    
  4. Создание пустого подмешать

    package filters; 
    import com.fasterxml.jackson.annotation.JsonFilter; 
    @JsonFilter("MyFilteringMixin") 
    public class MyFilteringMixin {} 
    
  5. Создание пустой подмешать создать класс MyPropertyFilter расширения SimpleBeanPropertyFilter и переопределения адаптировать этот метод serializeAsField(Object, JsonGenerator, SerializerProvider, PropertyWriter) вам нужно вызвать либо super.serializeAsField(pPojo, pJgen, pProvider, pWriter) или pWriter.serializeAsOmittedField(pPojo, pJgen, pProvider) в зависимости от того, хотите ли вы включить или отказаться от этого конкретной области.

Я добавил аннотацию к конкретным полям, которые я хотел изменить и допросил эту аннотацию, когда решал, какой из этих двух будет звонить. Я ввел роль безопасности и сохранил разрешенные роли в аннотации.

Это изменяет то, что Hal делится с вызывающим, а не то, что Хол держит в своем хранилище. Таким образом, вы можете преобразовать его в зависимости от того, кто является вызывающим.

Смежные вопросы