Spring boot 如何在Jackson中包装XML而不是JSON
我正在尝试使用Jackson将Spring boot 如何在Jackson中包装XML而不是JSON,spring-boot,jackson,Spring Boot,Jackson,我正在尝试使用Jackson将Foo对象列表序列化为XML和JSON(这是在SpringBootWeb应用程序中)。这个应用程序正在实现一个已经存在的API,所以我必须精确匹配现有的输出格式。我正在寻找的格式如下: 价值 其他 我使用API优先的方法,编写OpenAPI3规范并从中生成代码。此方法的规范将返回类型定义为Foos的数组: responses: '200': content: application/json
Foo
对象列表序列化为XML和JSON(这是在SpringBootWeb应用程序中)。这个应用程序正在实现一个已经存在的API,所以我必须精确匹配现有的输出格式。我正在寻找的格式如下:
价值
其他
我使用API优先的方法,编写OpenAPI3规范并从中生成代码。此方法的规范将返回类型定义为Foo
s的数组:
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/foo'
application/xml:
schema:
type: array
items:
$ref: '#/components/schemas/foo'
现在,当我为此生成代码时,我得到返回List
的API方法。这对于JSON来说很好,生成的正是我想要的。但是,对于XML,我得到如下结果:
@XmlRootElement(name="collection")
public class JaxbCollectionWrapper<T>{
@XmlAnyElement(lax=true)
protected Collection<T> list;
public JaxbCollectionWrapper(){}
public JaxbCollectionWrapper(Collection<T> list){
this.list=list;
}
public Collection<T> getList(){
return list;
}
}
价值
其他
因为我必须精确匹配现有的输出格式,所以这是行不通的。结构正确,但名称不正确。在大量搜索之后,我发现我应该创建一个包装类,因此我更改了API方法以返回FooCollection
,并定义了包装类:
@XmlRootElement(name=“collection”)
@JacksonXmlRootElement(localName=“collection”)
@XmlAccessorType(XmlAccessType.FIELD)
公共类食物收集{
@JacksonXmlProperty(localName=“foo”)
@JacksonXmlElementWrapper(useWrapping=false)
私有最终列表值;
公共图书馆馆藏(){
this.values=Collections.EMPTY_列表;
}
公共集合(列表值){
这个值=值;
}
}
现在,我的输出XML看起来正确,但JSON已损坏:
价值
其他
而JSON:
{
"values": [
{ "some": "value" },
{ "some": "other" }
]
}
在进一步搜索之后,解决方法是在FooCollection
类的内部列表中添加@JsonValue注释。这样做的结果是正确的JSON,但现在XML再次被破坏(实际上它根本无法生成输出,因为下面的XML无效):
价值
其他
我希望@JsonValue注释仅在生成JSON时生效。。。或者可能是一种完全不同的方法,因为这个兔子洞越来越深了。理想情况下,我希望在使用List
返回类型时使其工作,因为这在语义上是最正确的,但我似乎无法找到一种方法来定制生成的XML上的名称,而不编写包装类(这会导致我遇到的问题)
有什么想法吗?我最终用JAXB代替Jackson进行XML序列化,这样我就可以更好地控制输出格式。这可以通过向Spring MVC注册自定义转换器来实现:
converters.add(new JAXBCollectionWrapperHttpMessageConverter("com.mycompany.myapp.model"));
converters.add(new Jaxb2RootElementHttpMessageConverter());
converters.add(new MappingJackson2HttpMessageConverter());
JAXBCollectionWrapperHttpMessageConverter
是一个将集合包装到JAXBCollection
包装类中的类(为简洁起见,省略了错误处理):
public boolean canWrite(类clazz,@Nullable-MediaType-MediaType){
return Collection.class.isAssignableFrom(clazz)和canWrite(mediaType);
}
受保护的void writeToResult(对象o、HttpHeaders、结果){
...
marshaller.marshal(新的JaxbCollectionWrapper((Collection)o),result);
}
集合包装器类如下所示:
@XmlRootElement(name="collection")
public class JaxbCollectionWrapper<T>{
@XmlAnyElement(lax=true)
protected Collection<T> list;
public JaxbCollectionWrapper(){}
public JaxbCollectionWrapper(Collection<T> list){
this.list=list;
}
public Collection<T> getList(){
return list;
}
}
@XmlRootElement(name=“collection”)
公共类JaxbCollectionWrapper{
@xmlanyement(lax=true)
受保护的收集清单;
公共JaxbCollectionWrapper(){}
公共JaxbCollectionWrapper(集合列表){
this.list=list;
}
公共集合getList(){
退货清单;
}
}
@XmlRootElement(name="collection")
public class JaxbCollectionWrapper<T>{
@XmlAnyElement(lax=true)
protected Collection<T> list;
public JaxbCollectionWrapper(){}
public JaxbCollectionWrapper(Collection<T> list){
this.list=list;
}
public Collection<T> getList(){
return list;
}
}