Spring boot 如何在Jackson中包装XML而不是JSON

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

我正在尝试使用Jackson将
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;
    }
}