Spring MVC - 将RequestBody的未知参数转储到Map <string,string>变量的方法吗?

时间:2016-04-07 06:22:54

标签: java json spring spring-mvc

我的设置如下。

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"
}

让spring自动填充foo和bar到查询的foo和bar变量,以及other映射中的任何未定义参数(所以在这种情况下other将包含x - &gt; 3和ÿ - →4)。这样的事情是可配置的吗?我当前的临时工作是用@RequestBody Query query替换@RequestBody Map<String,String> mapping并迭代映射并将变量读入我的Query对象。我希望能够摆脱这样一个单调乏味的步骤。

2 个答案:

答案 0 :(得分: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 {
...
}

现在当你在下面这样的控制器中使用它时,Spring会自动使用你的反序列化器来构建你想要的对象:

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

答案 1 :(得分:0)

部分映射不起作用。可能有一种解决方法,但更容易的方法是引入包装器对象并更改您的json对象:

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