我想提供one全面的REST API,同时支持
JSON
和XML
。
领域模型是复杂类型,我们注意到,分别使用
JSON
和 XML
在同一模型上生成友好的 MappingJacksonHttpMessageConverter
和 JaxbMarshaller
往往会给出 可读的 XML 或可读的 JSON 1) 。
最好的方法是什么?
1) 由于地图、根标签和关系等对象在
json
中的建模方式与 xml
中不同,因此需要对要序列化的对象进行不同的设计,以获得整洁 json
和整洁 xml
。 jaxb 注释等实用程序只能做到这一点。
我能想到几个候选人
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
创建一个 JsonFoo
和 XmlFoo
我尝试了这个,结果有点复杂,因为视图必须知道如何解析,例如,将
Foo
解析为 JsonFoo
才能将其序列化为可读格式。
public class Foo {
public String serialize(Serializer s) {
return s.serialize(this);
}
}
基于一些仲裁参数让控制器注入正确的串行器
new Foo(new FooJsonSerializer());
new Foo(new FooXmlSerializer());
我正在当前项目中执行此操作,而没有使用
ContentNegotiatingViewResolver
。对于我的控制器中的one方法:
@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。
您应该使用 ContentNegotiatingViewResolver。
存在一个问题,即某些 XML 编组器无法正确映射 POJO 集合。 XStream 有解决方案(Moxy 也有吗?)。
从这里开始:
http://blog.springsource.org/2013/06/03/content-negotiation-using-views/
基本上,您使用 MappingJacksonView 和类似的 XML 视图,这是一种“假”视图,它使用 Jackson(或 XML 编组器)将 POJO 编组为正确的格式。
服务器将根据以下之一发回正确的类型:
就省略字段而言,您可以使用注释 @JsonIgnore(对于 Jackson)和/或 @XStreamOmitField(对于 XStream)。
你尝试过这个吗:
@RequestMapping(value = "/{id}",
method = RequestMethod.GET,
headers ={"Accept=application/json,application/xml"},
produces={"application/json", "application/xml"})
或者,您可以在 Spring 中配置
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer
.favorParameter(true)
.defaultContentType(MediaType.APPLICATION_JSON)
.mediaType("json", MediaType.APPLICATION_JSON)
.mediaType("xml", MediaType.APPLICATION_XML);
}
http://localhost:18050/api/ping/health?format=xml
http://localhost:18050/api/ping/health?format=json