Spring和JacksonJson,用视图序列化不同的领域

sti*_*vlo 10 serialization spring json spring-mvc jackson

之前的类似问题中,我询问过如何使用JacksonJson和Spring序列化两组不同的字段.

我的使用情况是典型的控制器映射与@ResponseBody注释直接返回一个特定的对象或对象的集合,即然后与JacksonJson渲染每当客户端增加了application/jsonAccept头部.

我有两个答案,第一个建议使用不同的getter列表返回不同的接口,第二个建议使用Json Views.

我没有问题要理解第一种方式,但是,对于第二种方法,在阅读文档之后JacksonJsonViews,我不知道如何用Spring实现它.

为了保持这个例子,我将在类Views中声明三个存根类:

// View definitions:
public class Views {
    public static class Public { }
    public static class ExtendedPublic extends PublicView { }
    public static class Internal extends ExtendedPublicView { }
}
Run Code Online (Sandbox Code Playgroud)

然后我要声明所提到的类:

public class PublicView { }   
public class ExtendedPublicView { }
Run Code Online (Sandbox Code Playgroud)

为什么他们在地球上声明空的静态类和外部的空类,我不知道.我知道他们需要一个"标签",但是View的静态成员就足够了.它不是ExtendedPublic延伸Public,因为它是合乎逻辑的,但它们实际上是完全无关的.

最后,bean将使用注释指定视图或视图列表:

//changed other classes to String for simplicity and fixed typo 
//in classname, the values are hardcoded, just for testing
public class Bean {
    // Name is public
    @JsonView(Views.Public.class)
    String name = "just testing";

    // Address semi-public
    @JsonView(Views.ExtendedPublic.class)
    String address = "address";

    // SSN only for internal usage
    @JsonView(Views.Internal.class)
    String ssn = "32342342";
}
Run Code Online (Sandbox Code Playgroud)

最后在Spring Controller中,我要考虑如何更改测试bean的原始映射:

@RequestMapping(value = "/bean") 
@ResponseBody
public final Bean getBean() {
    return new Bean();
}
Run Code Online (Sandbox Code Playgroud)

它说要打电话:

//or, starting with 1.5, more convenient (ObjectWriter is reusable too)
objectMapper.viewWriter(ViewsPublic.class).writeValue(out, beanInstance);
Run Code Online (Sandbox Code Playgroud)

所以我有一个ObjectMapper不知名的实例,out它不是典型的servlet PrintWriter out = response.getWriter();,但它是一个实例,JsonGenerator并且无法通过new运算符获得.所以我不知道如何修改方法,这里是一个不完整的尝试:

@RequestMapping(value = "/bean")
@ResponseBody
public final Bean getBean() throws JsonGenerationException, JsonMappingException, IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    JsonGenerator out; //how to create?
    objectMapper.viewWriter(Views.Public.class).writeValue(out, new Bean());
    return ??; //what should I return?
}
Run Code Online (Sandbox Code Playgroud)

所以我想知道是否有人成功使用JsonViewSpring以及他/她是如何使用的.整个概念看起来很有趣,但文档似乎缺乏,也缺少示例代码.

如果不可能,我将只使用相互扩展的接口.很抱歉这个问题很长.

Mar*_*itt 6

根据@igbopie和@chrislovecnm的答案,我整理了一个注释驱动的解决方案:

@Controller
public class BookService
{
    @RequestMapping("/books")
    @ResponseView(SummaryView.class)
    public @ResponseBody List<Book> getBookSummaries() {}

    @RequestMapping("/books/{bookId}")
    public @ResponseBody Book getBook(@PathVariable("bookId") Long BookId) {}
}
Run Code Online (Sandbox Code Playgroud)

在模型SummaryView上注释的位置Book如下:

@Data
class Book extends BaseEntity
{
    @JsonView(SummaryView.class)
    private String title;
    @JsonView(SummaryView.class)
    private String author;
    private String review;

    public static interface SummaryView extends BaseView {}
}

@Data
public class BaseEntity
{
    @JsonView(BaseView.class)
    private Long id;    
}

public interface BaseView {}
Run Code Online (Sandbox Code Playgroud)

HandlerMethodReturnValueHandler然后将自定义连接到Spring MVC的上下文以检测@ResponseView注释,并相应地应用Jackson视图.

在我的博客上提供了完整的代码.


chr*_*cnm 4

您需要手动连接 MappingJacksonHttpMessageConverter。在 spring 3.1 中,您可以使用 mvc xml 标签,如下所示:

<mvc:annotation-driven >
    <mvc:message-converter>
        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
    </mvc:message-converters>
</mvc:annotation-driven>
Run Code Online (Sandbox Code Playgroud)

不使用 spring 3.1 是相当难看的,它会为你节省大约 20 行 xml。mvc:annotation 标签做了很多事情。

您需要将对象映射器与正确的视图编写器连接起来。我最近注意到使用 @Configuration 类可以使像这样的复杂接线变得更加容易。使用 @Configuration 类并使用 MappingJacksonHttpMessageConverter 创建一个 @Bean,并将引用连接到该 bean 而不是上面的 MappingJacksonHttpMessageConverter。