将Spring MVC投影与JSON和Jackson结合使用 [英] Using Spring MVC projections with JSON and Jackson

查看:79
本文介绍了将Spring MVC投影与JSON和Jackson结合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在新版本的Spring Data(Fowler)中,可以将接口传递给Spring MVC控制器动作,然后Spring Data将自动创建代理实现并将值绑定到该代理对象.

In the new version of Spring Data (Fowler), one can pass an interface to Spring MVC controller actions, and Spring Data will then automatically create a proxy implementation and bind values to this proxy object.

An example is given in the blog post that describes some of the new features in 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) { ... }
}

我的问题是,用杰克逊反序列化JSON时是否还可以做到?例如,像这样:

My question is if this can also be done when deserializing JSON with Jackson? For instance, like this:

interface Form {
    @NotBlank String getName();
    @NotBlank String getText();
}

@Controller
@RequestMapping(value = "/guestbook")
class GuestbookController {
    @RequestMapping(method = RequestMethod.POST)
    String guestbook(@Valid @RequestBody Form form) { ... }
}

但是,这给出了以下异常:

However, this gives the following exception:

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

Can not construct instance of Form, problem: abstract types either need to be mapped to concrete types, have custom deserializer, or be instantiated with additional type information

我理解问题出在哪里,但是有没有一种解决方案不需要我创建实现我的接口的类或编写大量代码呢? 比这种方法更简单.因为否则我不妨采用DTO方法,但是我发现如果我可以像示例中那样简单地使用接口,那就太酷了.

I understand what the problem is, but is there a solution that does not require me to create a class that implements my interface or write a lot of code? One that is simpler than this approach. Because otherwise I might as well go with a DTO approach, but I just found it to be super cool if I could simply use an interface as in the example.

通过上述方法,我可以很好地使用DTO类(或避免使用JSON),但是使用类似博客文章示例中的接口将是一件很整洁的事情.但是,在反序列化JSON时,杰克逊(Jackson)库是否有可能?

I can use a DTO class just fine with the above approach (or avoid using JSON), but using an interface like in the blog post's example would be neat. But is this possible with the Jackson library when deserializing JSON?

推荐答案

您可以使用 Jackson Mr Bean模块,它正是您想要的功能.

You could use Jackson Mr Bean module, which does exactly what you want.

要使用它,只需下载特定的依赖项并将其设置为基础ObjectMapper实例的模块:

To use it, just download the specific dependency and set it as a module to the underlying ObjectMapper instance:

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

上面的小程序产生以下输出:

The little program above produces the following output:

John, 23, 1001 5th Ave, New York
Jean Jacques, 26, 1001 Champs Elysees Blvd, Paris
Oscar Ruben, 54, 1001 9th July Ave, Buenos Aires

这篇关于将Spring MVC投影与JSON和Jackson结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆