使用Spring MVC投影与JSON和Jackson

4
在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) { ... }
}

然而,这会导致以下异常:

无法构造表单的实例,问题:抽象类型需要映射到具体类型,具有自定义反序列化器或使用其他类型信息进行实例化

我了解问题所在,但是否有解决方案不需要我创建一个实现我的接口的类或编写大量代码呢?是否有一种比此方法更简单的方法?因为否则,我可能会采用DTO方法,但我发现如果我可以像示例中那样仅使用接口,那就太酷了。
我可以使用DTO类来处理上述方法(或避免使用JSON),但是在反序列化JSON时是否可以使用像博客文章示例中的接口与Jackson库一起使用?
1个回答

1
你可以使用 Jackson Mr Bean模块,它正好符合你的要求。
只需下载特定依赖项并将其设置为底层 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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接