2017-05-31 45 views
2

我在java Rest Api中使用Jackson來處理請求參數。Jackson在地圖中捕獲無法識別的字段

我Bean類:

public class ZoneModifBeanParam extends ModifBeanParam<Zone> { 
@FormParam("type") 
private String type; 

@FormParam("geometry") 
private Geometry geometry; 

@FormParam("name") 
private String name; 

... 

我的API接口:

@POST 
@Consumes("application/json") 
@Produces("application/json; subtype=geojson") 
@ApiOperation(value = "Create a zone", notes = "To create a zone") 
public Response createZone(ZoneModifBeanParam zoneParam) { 

... 

這工作正常,但我需要接收不是由我的豆在地圖指定的其他PARAMS。 例子:

{ 
    "geometry": {...}, 
    "name": "A circle name", 
    "type": "4", 
    "hello": true 
} 

通過接收這個我需要在地圖存儲(名爲unrecognizedFields和我的豆聲明)夫妻(「你好」,真)。

是否有任何註釋或對象允許這樣做?

+0

您可以通過配置ObjectMapper來安全地忽略無法識別的字段,但要專門將它們作爲「Map」字段的鍵值對,則需要您自己的反序列化器。 – Mena

回答

4

只需使用@JsonAnySetter。這就是它的目的。這裏是一個測試用例

public class JacksonTest { 

    public static class Bean { 
     private String name; 
     public String getName() { return this.name; } 
     public void setName(String name) { this.name = name; } 

     private Map<String, Object> unrecognizedFields = new HashMap<>(); 

     @JsonAnyGetter 
     public Map<String, Object> getUnrecognizedFields() { 
      return this.unrecognizedFields; 
     } 

     @JsonAnySetter 
     public void setUnrecognizedFields(String key, Object value) { 
      this.unrecognizedFields.put(key, value); 
     } 
    } 

    private final String json 
      = "{\"name\":\"paul\",\"age\":600,\"nickname\":\"peeskillet\"}"; 
    private final ObjectMapper mapper = new ObjectMapper(); 

    @Test 
    public void testDeserialization() throws Exception { 
     final Bean bean = mapper.readValue(json, Bean.class); 
     final Map<String, Object> unrecognizedFields = bean.getUnrecognizedFields(); 

     assertEquals("paul", bean.getName()); 
     assertEquals(600, unrecognizedFields.get("age")); 
     assertEquals("peeskillet", unrecognizedFields.get("nickname")); 
    } 
} 

@JsonAnyGetter用於序列化端。當您序列化bean時,您將看不到JSON中的unrecognizedFields。相反,地圖中的所有屬性都將被序列化爲JSON中的頂級屬性。

+0

這正是我所期待的!謝謝你的幫助 – Guinoutortue

2

您可以通過配置ObjectMapper來安全地忽略無法識別的字段,但要專門將它們設置爲Map字段的鍵值對,您需要自己的反序列化器。

這裏有一個(重簡體)例如:

鑑於你的POJO ...

@JsonDeserialize(using=MyDeserializer.class) 
class Foo { 
    // no encapsulation for simplicity 
    public String name; 
    public int value; 
    public Map<Object, Object> unrecognized; 
} 

......和您的自定義解串...

class MyDeserializer extends JsonDeserializer<Foo> { 
    @Override 
    public Foo deserialize(JsonParser p, DeserializationContext ctxt) 
      throws IOException, JsonProcessingException { 
     // new return object 
     Foo foo = new Foo(); 
     // setting unrecognized container 
     Map<Object, Object> unrecognized = new HashMap<>(); 
     foo.unrecognized = unrecognized; 
     // initializing parsing from root node 
     JsonNode node = p.getCodec().readTree(p); 
     // iterating node fields 
     Iterator<Entry<String, JsonNode>> it = node.fields(); 
     while (it.hasNext()) { 
      Entry<String, JsonNode> child = it.next(); 
      // assigning known fields 
      switch (child.getKey()) { 
       case "name": { 
        foo.name = child.getValue().asText(); 
        break; 
       } 
       case "value": { 
        foo.value = child.getValue().asInt(); 
        break; 
       } 
       // assigning unknown fields to map 
       default: { 
        foo.unrecognized.put(child.getKey(), child.getValue()); 
       } 
      } 

     } 
     return foo; 
    } 
} 

然後,在某處...

ObjectMapper om = new ObjectMapper(); 
Foo foo = om.readValue("{\"name\":\"foo\",\"value\":42,\"blah\":true}", Foo.class); 
System.out.println(foo.unrecognized); 

輸出

{blah=true} 
+0

你的解決方案工作正常,我測試過!但peeskillet解決方案更符合我的Forms註釋。感謝您的幫助 – Guinoutortue

相關問題