9

我想提供一个全面的 REST API,同时支持JSONXML.

领域模型是复杂类型的,我们注意到,要在同一模型上使用和分别生成友好的JSON和易于给出可读的 XML可读的 JSON 1)XMLMappingJacksonHttpMessageConverterJaxbMarshaller

最好的方法是什么?

1) 由于映射、根标签和关系等对象的建模方式与 in 不同jsonxml因此需要对要序列化的对象进行不同的设计,以既 tidyjson又 tidy xml。诸如 jaxb 注释之类的实用程序只能做到这一点。


我能想到几个候选人

1) 创建一个 json 和 xml 控制器/模型

public class Controller { 
   public Foo foo() { 
       return new Foo(); 
   } 
}

public class XmlController extends Controller {
   @Override
   public XmlFoo foo() { 
       return new new XmlFoo(super.foo()); 
   } 
}

public class JsonController extends Controller {
   @Override
   public JsonFoo foo() { 
       return new JsonFoo(super.foo()); 
   } 
}

给定一个模型对象,Foo创建一个JsonFooXmlFoo

2)编写自定义消息转换器

我试过了,结果有点复杂,因为视图必须知道如何解析,例如 aFoo到 aJsonFoo才能将其序列化为可读格式。

3)让每个模型对象序列化自己,例如,

public class Foo {
    public String serialize(Serializer s) {
       return s.serialize(this);
    }
}

基于一些仲裁参数让控制器注入正确的序列化器

new Foo(new FooJsonSerializer());
new Foo(new FooXmlSerializer());
4

3 回答 3

5

我在当前项目中执行此操作而不使用ContentNegotiatingViewResolver. 对于我的控制器中的一种方法:

@RequestMapping(value = "/test", method = RequestMethod.GET)
@ResponseBody
public HttpEntity<BasicResponse> getBasicResponse() {
    return new HttpEntity<BasicResponse>(new BasicResponse());
}

我可以根据Accept请求标头接收以下输出。

接受:application/xml(在类路径上需要 JAXB2)

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<basicResponse>
    <errors>
        <message>test1</message>
        <message>test2</message>
    </errors>
</basicResponse>

接受:application/json(在类路径中需要 Jackson)

{
    "errors" : ["test1", "test2"]
}

我的响应对象很简单,并使用普通注释:

package org.mypackage.response;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class BasicResponse {

    @XmlElementWrapper(name = "errors")
    @XmlElement(name = "message")
    private List<String> errors = new ArrayList<String>();

    public BasicResponse() {
        this.errors.add("test1");
        this.errors.add("test2");
    }

    public List<String> getErrors() {
        return errors;
    }

}

SpringSource spring-mvc-showcase 项目也是一个有用的资源。我认为他们将不同方法的转换分开,但我肯定是为一种方法做的。

我不能完全通过您的问题来判断...但是如果您希望序列化输出的内容不止于此,@chrylis 是正确的,因为自定义序列化程序将是您的下一步。但是我遇到的所有事情(可能会变得非常复杂,在我的响应中有嵌套对象)都可以完美地转换为有效的 XML 或 JSON。

于 2013-08-20T16:57:40.743 回答
1

您应该使用ContentNegotiatingViewResolver

存在一个问题,即 POJO 集合未与某些 XML 编组器正确映射。XStream 对此有解决方案(Moxy 也是?)。

这是一个开始的地方:

http://blog.springsource.org/2013/06/03/content-negotiation-using-views/

基本上,您使用 MappingJacksonView 和类似的 XML 视图,这是一种“假”视图,使用 Jackson(或 XML 编组器)将您的 POJO 编组为正确的格式。

服务器将根据以下之一发回正确的类型:

  • HTTP 接受标头
  • “文件类型扩展名”,例如“.json”
  • 查询字符串参数,例如“format=json”
于 2013-08-20T16:41:10.033 回答
0

至于省略字段,您可以使用注解@JsonIgnore(for Jackson) 和/或@XStreamOmitField(for XStream)。

你试过这个:

@RequestMapping(value = "/{id}", 
method = RequestMethod.GET,
headers ={"Accept=application/json,application/xml"},
produces={"application/json", "application/xml"})
于 2014-08-26T20:41:11.013 回答