在新版本的 Spring Data (Fowler) 中,可以将一个接口传递给 Spring MVC 控制器操作,然后 Spring Data 将自动创建一个代理实现并将值绑定到该代理对象。
博客文章中给出了一个示例,描述了 Spring Data Fowler 中的一些新功能:
interface Form {
@NotBlank String getName();
@NotBlank String getText();
}
@Controller
@RequestMapping(value = "/guestbook")
class GuestbookController {
@RequestMapping(method = RequestMethod.GET)
String guestbook(Form form, Model model) { ... }
@RequestMapping(method = RequestMethod.POST)
String guestbook(@Valid Form form, Errors errors, Model model) { ... }
}
我的问题是,用 Jackson 反序列化 JSON 时是否也可以这样做?例如,像这样:
interface Form {
@NotBlank String getName();
@NotBlank String getText();
}
@Controller
@RequestMapping(value = "/guestbook")
class GuestbookController {
@RequestMapping(method = RequestMethod.POST)
String guestbook(@Valid @RequestBody Form form) { ... }
}
但是,这会产生以下例外:
无法构造 Form 实例,问题:抽象类型 需要映射到具体类型,具有自定义反序列化器,或者 使用附加类型信息实例化
我明白问题所在,但是有没有一种解决方案不需要我创建一个实现我的接口的类或编写大量代码?一种比这种方法更简单的方法。因为否则我可能会采用 DTO 方法,但我发现如果我可以像示例中那样简单地使用接口,那就太酷了。 我可以通过上述方法使用 DTO 类(或避免使用 JSON),但使用像博客文章示例中那样的接口会更简洁。但是在反序列化 JSON 时,Jackson 库可以实现这一点吗?
,它正是您想要的。 要使用它,只需下载特定的依赖项并将其设置为底层
ObjectMapper
实例的模块即可:
import java.io.IOException;
import java.util.List;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.mrbean.MrBeanModule;
public class AbstractPojosExample {
public interface Person {
String getName();
int getAge();
Address getAddress();
default String asString() {
return String.format("%s, %d, %s", this.getName(), this.getAge(), this.getAddress().asString());
}
}
public interface Address {
String getStreet();
String getCity();
default String asString() {
return String.format("%s, %s", this.getStreet(), this.getCity());
}
}
private void run() throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new MrBeanModule());
String json = "[ { \"name\": \"John\", \"age\": 23, "
+ "\"address\": { \"street\": \"1001 5th Ave\", \"city\": \"New York\" } }, "
+ "{ \"name\": \"Jean Jacques\", \"age\": 26 , "
+ "\"address\": { \"street\": \"1001 Champs Elysees Blvd\", \"city\": \"Paris\" } }, "
+ "{ \"name\": \"Oscar Ruben\", \"age\": 54, "
+ "\"address\": { \"street\": \"1001 9th July Ave\", \"city\": \"Buenos Aires\" } } ]";
System.out.println(json);
List<Person> people = mapper.readValue(json, new TypeReference<List<Person>>() {});
people.stream().map(Person::asString).forEach(System.out::println);
}
public static void main(String[] args) throws IOException {
AbstractPojosExample example = new AbstractPojosExample();
example.run();
}
}
对于给定的 json:
[
{
"name": "John",
"age": 23,
"address": {
"street": "1001 5th Ave",
"city": "New York"
}
},
{
"name": "Jean Jacques",
"age": 26,
"address": {
"street": "1001 Champs Elysees Blvd",
"city": "Paris"
}
},
{
"name": "Oscar Ruben",
"age": 54,
"address": {
"street": "1001 9th July Ave",
"city": "Buenos Aires"
}
}
]
上面的小程序产生以下输出:
John, 23, 1001 5th Ave, New York
Jean Jacques, 26, 1001 Champs Elysees Blvd, Paris
Oscar Ruben, 54, 1001 9th July Ave, Buenos Aires