如何让Spring控制器接受多种类型的JSON
我有一个SpringREST服务(用Groovy编写;尽管这不重要),它公开了一个安全端点,如下所示:如何让Spring控制器接受多种类型的JSON,json,spring,spring-mvc,groovy,Json,Spring,Spring Mvc,Groovy,我有一个SpringREST服务(用Groovy编写;尽管这不重要),它公开了一个安全端点,如下所示: class AppData { String id String payload String fizzbuzz } @RequestMapping(method=RequestMethod.POST) @ResponseStatus(value = HttpStatus.OK) @ResponseBody AppResponse onAppData(@Request
class AppData {
String id
String payload
String fizzbuzz
}
@RequestMapping(method=RequestMethod.POST)
@ResponseStatus(value = HttpStatus.OK)
@ResponseBody AppResponse onAppData(@RequestBody AppData appData) {
// Does some processing on appData and then saves
// its 'payload' field to a MongoDB
}
当它接收到以下形式的JSON时,它的效果非常好:
{
"id" : "12345",
"payload" : "Please save me to a MongoDB",
"fizzbuzz" : "wakka wakka"
}
我在这里使用Jackson来处理JSON序列化
问题是,我现在希望有效负载
属性是真正的JSON,而不是字符串。因此,我希望能够向端点发送如下内容:
{
"id" : "12345",
"payload" : {
"foo" : 24,
"bar" : false,
"whistlefeather" : "Yes of course"
},
"fizzbuzz" : "wakka wakka"
}
并将有效载荷正确保存到MongoDB。但问题是:
许多不同的团队(可能有数百个)将发送此端点AppData
,他们的所有有效负载看起来将完全不同(每个团队都有不同的有效负载,他们想发送给我并保存在MongoDB中)。我不想为我加入的每个新团队编写一个新的端点和AppData
子类(从而将该端点公开给)
我有没有办法:
- 让我的终点保持原样;但是
- 允许
属性接受任何形式的JSONAppData#payload
负载
也是JSON(并且不是字符串),Spring只返回一个400,响应体为空。之所以会发生这种情况,是因为Spring期望payload
是一个字符串,但看到它是一个JSON对象
关于我可以在
AppData
类中做些什么来处理这个问题,或者关于这里的最佳实践是什么的任何想法?使用JsonNode作为有效负载的类型:
public class AppData {
String id;
JsonNode payload;
String fizzbuzz;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public JsonNode getPayload() {
return payload;
}
public void setPayload(JsonNode payload) {
this.payload = payload;
}
public String getFizzbuzz() {
return fizzbuzz;
}
public void setFizzbuzz(String fizzbuzz) {
this.fizzbuzz = fizzbuzz;
}
public static void main(String[] args) throws IOException {
String json = "{\n" +
" \"id\" : \"12345\",\n" +
" \"payload\" : {\n" +
" \"foo\" : 24,\n" +
" \"bar\" : false,\n" +
" \"whistlefeather\" : \"Yes of course\"\n" +
" },\n" +
" \"fizzbuzz\" : \"wakka wakka\"\n" +
"}";
ObjectMapper om = new ObjectMapper();
AppData appData = om.readValue(json, AppData.class);
System.out.println("appData ID = " + appData.getId());
System.out.println("appData fizzbuzz = " + appData.getFizzbuzz());
System.out.println("appData payload = " + appData.getPayload());
String json2 = "{\n" +
" \"id\" : \"12345\",\n" +
" \"payload\" : \"Please save me to a MongoDB\",\n" +
" \"fizzbuzz\" : \"wakka wakka\"\n" +
"}";
appData = om.readValue(json2, AppData.class);
System.out.println("appData ID = " + appData.getId());
System.out.println("appData fizzbuzz = " + appData.getFizzbuzz());
System.out.println("appData payload = " + appData.getPayload());
}
}
输出:
appData ID = 12345
appData fizzbuzz = wakka wakka
appData payload = {"foo":24,"bar":false,"whistlefeather":"Yes of course"}
appData ID = 12345
appData fizzbuzz = wakka wakka
appData payload = "Please save me to a MongoDB"
请注意,要获取有效负载的JSON字符串,不应该像上面的示例中那样使用toString()。您应该使用
objectMapper.writeValueAsString(有效负载)
您可以尝试使用映射,我不知道它在Groovy中是什么,但这将是Java中的结构
public class AppData {
String id;
Map<String, Object> payload;
String fizzbuzz;
}
公共类AppData{
字符串id;
地图有效载荷;
弦乐嘶嘶作响;
}
Oh@JB Nizet,一如既往,你是我的英雄;非常感谢。