Java 带有 JSON 和 XML 的 Spring REST
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18335002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring REST with both JSON and XML
提问by Johan Sj?berg
I want to provide onecomprehensive REST API with support for both JSON
and XML
.
我想提供一个与两个全面支持REST APIJSON
和XML
。
The domain model is of complex type and we note that to produce friendly JSON
and XML
on the same model using MappingHymansonHttpMessageConverter
and JaxbMarshaller
respectively tends to give eitherreadable XML or readable JSON 1).
域模型是复杂的类型的,并且我们注意到,以产生友好JSON
和XML
上使用相同的模型MappingHymansonHttpMessageConverter
和JaxbMarshaller
分别往往给任一可读XML或JSON可读1) 。
What's the best way to proceed?
最好的方法是什么?
1) Due to how objects such as maps, root tags and relations are modelled differently in json
than in xml
, the objects to serialize needs to be designed differently to get both tidy json
and tidy xml
. Utilities such as jaxb annotations only goes that far.
1) 由于映射、根标签和关系等对象的建模方式与 injson
和 in不同xml
,因此需要将要序列化的对象设计为不同的 tidyjson
和 tidy xml
。诸如 jaxb 注释之类的实用程序只能做到这一点。
I can think of a few candidates
我能想到几个候选人
1) Create both a json and xml controller/model
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());
}
}
Given a model object Foo
create a JsonFoo
and XmlFoo
给定一个模型对象,Foo
创建一个JsonFoo
和XmlFoo
2) Write a custom message converter
2)编写自定义消息转换器
I tried this and it turned out to be a bit complicated since the view must know how to resolve e.g., a Foo
to a JsonFoo
to be able to serialize it into a readable format.
我试过这个,结果有点复杂,因为视图必须知道如何解析,例如,aFoo
到 aJsonFoo
才能将其序列化为可读格式。
3) Let each model object serialize itself, e.g.,
3)让每个模型对象序列化自己,例如,
public class Foo {
public String serialize(Serializer s) {
return s.serialize(this);
}
}
Based on some arbitration parameter let the controller inject the correct serializer
基于一些仲裁参数让控制器注入正确的串行器
new Foo(new FooJsonSerializer());
new Foo(new FooXmlSerializer());
采纳答案by trebor
I'm doing this in a current project without using a ContentNegotiatingViewResolver
. For onemethod in my controller:
我在当前项目中这样做,没有使用ContentNegotiatingViewResolver
. 对于我的控制器中的一种方法:
@RequestMapping(value = "/test", method = RequestMethod.GET)
@ResponseBody
public HttpEntity<BasicResponse> getBasicResponse() {
return new HttpEntity<BasicResponse>(new BasicResponse());
}
I can receive the following output based on the Accept
request header.
我可以根据Accept
请求标头收到以下输出。
Accept: application/xml(requires JAXB2 on the classpath)
接受:application/xml(在类路径上需要 JAXB2)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<basicResponse>
<errors>
<message>test1</message>
<message>test2</message>
</errors>
</basicResponse>
Accept: application/json(requires Hymanson on the classpath)
接受:application/json(在类路径上需要 Hymanson)
{
"errors" : ["test1", "test2"]
}
My response object is simple and uses normal annotations:
我的响应对象很简单,使用普通注释:
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;
}
}
The SpringSource spring-mvc-showcase projectis also a helpful resource. I think they separate the conversions for different methods, but I am definitely doing this for one method.
在SpringSource的弹簧MVC-展示项目也是一个有用的资源。我认为他们将不同方法的转换分开,但我绝对是为一种方法这样做。
I can't quite tell by your question...but if you're looking to serialize the output more than that, @chrylis is correct in that a custom serializer would be your next move. But everything I've ran into (which can get pretty complex, with nested objects in my response) converts perfectly to valid XML or JSON.
你的问题我不太清楚……但如果你希望序列化输出不止于此,@chrylis 是正确的,因为自定义序列化程序将是你的下一步。但是我遇到的所有事情(这可能会变得非常复杂,在我的响应中包含嵌套对象)都可以完美地转换为有效的 XML 或 JSON。
回答by Neil McGuigan
You should use the ContentNegotiatingViewResolver.
您应该使用ContentNegotiatingViewResolver。
There is an issue in that a collection of POJOs are not mapped correctly with some XML marshallers. XStream has solutions for this (Moxy too?).
存在一个问题,即 POJO 集合未与某些 XML 编组器正确映射。XStream 对此有解决方案(也有 Moxy?)。
Here's a place to start:
这是一个开始的地方:
http://blog.springsource.org/2013/06/03/content-negotiation-using-views/
http://blog.springsource.org/2013/06/03/content-negotiation-using-views/
Basically, you use a MappingHymansonView and a similar one for XML, which is a "fake" view that uses Hymanson (or an XML marshaller) to marshall your POJO(s) to the correct format.
基本上,您使用 MappingHymansonView 和类似的 XML,这是一个“假”视图,它使用 Hymanson(或 XML 编组器)将您的 POJO 编组为正确的格式。
The server will send back the correct type based on one of:
服务器将根据以下之一发回正确的类型:
- the HTTP Accept header
- a "filetype extension", such as ".json"
- a querystring parameter, such as "format=json"
- HTTP 接受标头
- “文件类型扩展名”,例如“.json”
- 查询字符串参数,例如“format=json”
回答by Justin
As far as omitting fields, you cans use annotations @JsonIgnore(for Hymanson) and/or @XStreamOmitField(for XStream).
至于省略字段,您可以使用注释@JsonIgnore(for Hymanson) 和/或@XStreamOmitField(for XStream)。
Did you try this:
你试过这个吗:
@RequestMapping(value = "/{id}",
method = RequestMethod.GET,
headers ={"Accept=application/json,application/xml"},
produces={"application/json", "application/xml"})