2014-03-24 91 views
0

如何筛选从spring rest web服务返回的json响应。如何筛选从spring rest web服务返回的json响应

当使用调用customEvents时,我只需要输出eventId和Event名称。当询问特定事件我需要 发送事件的全部细节。

Class CustomEvent{ 

long id; 
String eventName; 
Account createdBy; 
Account modifiedBy; 
.. 


} 

Class Account{ 
long id; 
String fname; 
String lname; 
.... 

} 


@Controller 
public class CustomEventService 
{ 
    @RequestMapping("/customEvents") 
    public @ResponseBody List<CustomEvent> getCustomEventSummaries() {} 

    @RequestMapping("/customEvents/{eventId}") 
    public @ResponseBody CustomEvent getCustomEvent(@PathVariable("eventId") Long eventId) {} 
} 

我该如何达到上述目的?目前我正在使用spring 3.1。它是否支持3.1版本以上版本或更高版本

+0

您是否使用Jackson映射到JSON与MappingJacksonHttpMessageConverter或MappingJackson2HttpMessageConverter? – geoand

+0

从getCustomEventSummaries()返回'Map <[ID_TYPE],[NAME_TYPE]>'是什么问题?或者将'CustomEvent'的所有其他特性设置为'null'。 –

+0

我正在使用MappingJackson2HttpMessageConverter – Sam

回答

1

我可以想到两种解决方案,它们都利用了Jackson的mixin功能。

如果您所描述的内容将被复制到代码的其他部分,则第一个解决方案要复杂得多,但这是一个非常棒的方法,请参阅this链接。 会发生什么是你定义了一个方面,它应用了你在JsonFilter注解中设置的特定混合(在你的情况下是CustomEventMixin)。

第二种解决方案是简单得多,并包括使用在自己的杰克逊对象映射器(而不是委托该责任字符串),如下面的代码

@Controller 
public class EventController { 


    private ObjectMapper objectMapper = new ObjectMapper(); 

    public EventController(ObjectMapper objectMapper) { 
     this.objectMapper = objectMapper; 
     objectMapper.addMixInAnnotations(CustomEvent.class, CustomEventMixin.class); 
    } 

    @RequestMapping("/customEvents") 
    @ResponseBody 
    public String suggest() { 
     return objectMapper.writeValueAsString(getCustomEvents(), new TypeReference<List<CustomEvent>>() {}); 
    } 
} 

在您需要定义根据CustomEventMixin两种情况杰克逊规则

UPDATE

一个例子的混合类将是(说你要忽略ID)

public interface CustomEventMixin { 

    String name; 

    @JsonIgnore 
    String id; 
} 
+0

如何创建CustomEventMixin类 – Sam

+1

' @ JsonIgnore'是事情。史诗!在正确的位置用一行代码修复完整的REST设置。 –

+0

@SimonK。尼斯! – geoand

2

您可以使用@JsonFilter进行存档。

POJO的:

@JsonFilter("myFilter") 
public class User { 
    .... 
} 

控制器:

public String getUser(
      @RequestParam(value="id") String id, 
      @RequestParam(value="requiredFields",required=false) String requiredFields 
     ) throws JsonParseException, JsonMappingException, IOException { 

    //Get User 
    User user = userService.getUser(id); 
    //Start 
    ObjectMapper mapper = new ObjectMapper(); 
    // and then serialize using that filter provider: 
    String json=""; 
    try { 
     if (requiredFields!= null) { 
      String[] fields = requiredFields.split("\\,"); 

      FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter", 
      SimpleBeanPropertyFilter.filterOutAllExcept(new HashSet<String>(Arrays 
        .asList(fields)))); 

      json = mapper.filteredWriter(filters).writeValueAsString(user);//Deprecated 
     } else { 
      SimpleFilterProvider fp = new SimpleFilterProvider().setFailOnUnknownId(false); 
      mapper.setFilters(fp); 
      json =mapper.writeValueAsString(user); 
     } 
    } catch (JsonGenerationException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (JsonMappingException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

    return json; 
} 

获取网址:..... &使用requiredfields = ID,名字,年龄

0

可以使用@JsonView注释本目的。但不幸的是,它仅适用于4.x及更高版本。

这是我知道的最彻底的方法:

public class View { 
    public interface Summary {} 
    public interface Details extends Summary{} 
} 

Class CustomEvent{ 
    @JsonView(View.Summary.class) 
    long id; 

    @JsonView(View.Summary.class) 
    String eventName; 

    @JsonView(View.Details.class) 
    Account createdBy; 

    @JsonView(View.Details.class) 
    Account modifiedBy; 
} 

@Controller 
public class CustomEventService 
{ 
    @JsonView(View.Summary.class) 
    @RequestMapping("/customEvents") 
    public @ResponseBody List<CustomEvent> getCustomEventSummaries() {} 

    @RequestMapping("/customEvents/{eventId}") 
    public @ResponseBody CustomEvent getCustomEvent(@PathVariable("eventId") Long eventId) {} 
} 

请记住,由不具备@JsonView注释默认字段也序列化。这就是为什么你需要注解他们。

欲了解更多信息,请阅读:https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring

0

我有我的现有项目类似的要求。作为单个对象被多个控制器使用,引入视图是一种痛苦。这也不是一个干净的解决方案来实现过滤器。所以我决定在发送给客户端之前,从Controller中的DTO中清除这些值。所以我自己的方法(这可能需要更多的执行时间)来解决这个问题。

public static void includeFields(Object object, String... includeFields) { 
     for (PropertyDescriptor propertyDescriptor : PropertyUtils.getPropertyDescriptors(object)) { 
      if (!Arrays.asList(includeFields).contains(propertyDescriptor.getName())) { 
       clearValues(object, propertyDescriptor); 
      } 
     } 
    } 

    public static void excludeFields(Object object, String... includeFields) { 
     for (PropertyDescriptor propertyDescriptor : PropertyUtils.getPropertyDescriptors(object)) { 
      if (Arrays.asList(includeFields).contains(propertyDescriptor.getName())) { 
       clearValues(object, propertyDescriptor); 
      } 
     } 
    } 

    private static void clearValues(Object object, PropertyDescriptor propertyDescriptor) { 
     try { 
      if(propertyDescriptor.getPropertyType().equals(boolean.class)) { 
       PropertyUtils.setProperty(object, propertyDescriptor.getName(), false); 
      } else { 
       PropertyUtils.setProperty(object, propertyDescriptor.getName(), null); 
      } 
     } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { 
      //TODO 
      e.printStackTrace(); 
     } 
    } 

缺点是boolean字段将总是具有值,从而将存在于所述有效载荷。至少这帮助我给出了动态解决方案并减少了有效载荷中的许多领域。

+0

PropertyUtils在哪里? –

+1

该类是'org.apache.commons.beanutils.PropertyUtils',你可以在'commons-beanutils.jar'中找到它。 – Maz