2014-03-24 89 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