2016-04-07 1 views
0

私は以下のような設定をしています。Spring MVC - RequestBodyの未知のパラメータをMap <String、String>変数にダンプする方法ですか?

public class TestController { 
    @RequestMapping(method = RequestMethod.POST, value = "/test") 
    public void readQuery(@RequestBody Query query) { 
    } 
} 
public class Query { 
    private String foo; 
    private String bar; 
    private Map<String,String> other; 
} 

私のようなJSONオブジェクトを投稿できるようにしたいと思います:

{ 
    "foo":"1", 
    "bar":"2", 
    "x":"3", 
    "y":"4" 
} 

そして春が自動的にFOOを移入し、クエリのFOOにバーがあり、 bar変数、および未定義のパラメータをotherマッピングに追加します(この場合、otherにはx - > 3およびy - > 4が含まれます)。そのようなことは設定可能ですか?私の現在の一時的な回避策は、@RequestBody Query query@RequestBody Map<String,String> mappingに置き換え、マッピングを反復し、変数をQueryオブジェクトに読み込むことです。私はこのような退屈なステップを取り除くことができるのが大好きです。

+0

カスタムデシリアライザとリフレクションを使用すると、簡単に実行できます。私が言ったことが意味をなさない場合、私はあなたに例を示すことができます。 – dambros

+0

私はあなたが意味することを知っていると思うが、私は例を見てみたい! – Shark

+0

あなたはジャクソンを使用しています、そうですか? – dambros

答えて

1

私が先にコメントしたよう、ここにあなたが欲しいものを行うための一例です。

カスタムデシリアライザを作成します。

public class QueryDeserializer extends JsonDeserializer<Query> { 

    @Override 
    public Query deserialize(JsonParser jp, DeserializationContext ctxt) 
      throws IOException { 

     JsonNode node = jp.getCodec().readTree(jp); 

     Iterator<Entry<String, JsonNode>> nodeIterator = node.fields(); 

     Query query = new Query(); 
     Map<String, String> other = new HashMap<>(); 

     while (nodeIterator.hasNext()) { 
      Map.Entry<String, JsonNode> entry = nodeIterator.next(); 
      Field field = getField(entry.getKey()); 

      if (field != null) { 
       try { 
        field.set(query, entry.getValue().textValue()); 
       } catch (IllegalAccessException e) { 
        e.printStackTrace(); 
       } 
      } else { 
       other.put(entry.getKey(), entry.getValue().textValue()); 
      } 
     } 

     if (other.size() != 0) { 
      query.setOther(other); 
     } 

     return query; 
    } 

    public static Field getField(String entryName) { 
     for (Field field : Query.class.getDeclaredFields()) { 
      field.setAccessible(true); 
      String fieldName; 
      if (field.isAnnotationPresent(JsonProperty.class)) { 
       fieldName = field.getAnnotation(JsonProperty.class).value(); 
      } else { 
       fieldName = field.getName(); 
      } 
      if (entryName.equalsIgnoreCase(fieldName)) { 
       return field; 
      } 
     } 
     return null; 
    } 
} 

デシリアライザを登録します。あなたは以下のようなコントローラで使用するとき

@JsonDeserialize(using = QueryDeserializer.class) 
public class Query { 
... 
} 

は今、春が自動的にあなたのようなオブジェクトを構築するためにあなたのデシリアライザを使用します。必要:

@RequestMapping(value = "/test", method = RequestMethod.PUT) 
public String test(@RequestBody Query query) {} 
0

部分的なマッピングは機能しません。そこ回避策かもしれないが、もっと簡単な方法は、ラッパーオブジェクトを導入して、JSONオブジェクトを変更するには、次のようになります。

{ 
"foo":"1", 
"bar":"2", 
"other":{ 
    "x":"3", 
    "y":"4" 
} 
} 
関連する問題