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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:38:09  来源:igfitidea点击:

Spring REST with both JSON and XML

javajsonspringrestspring-mvc

提问by Johan Sj?berg

I want to provide onecomprehensive REST API with support for both JSONand XML.

我想提供一个与两个全面支持REST APIJSONXML

The domain model is of complex type and we note that to produce friendly JSONand XMLon the same model using MappingHymansonHttpMessageConverterand JaxbMarshallerrespectively tends to give eitherreadable XML or readable JSON 1).

域模型是复杂的类型的,并且我们注意到,以产生友好JSONXML上使用相同的模型MappingHymansonHttpMessageConverterJaxbMarshaller分别往往给任一可读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 jsonthan in xml, the objects to serialize needs to be designed differently to get both tidy jsonand 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 Foocreate a JsonFooand XmlFoo

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

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 Footo a JsonFooto 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 Acceptrequest 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"})