SpringBoot:使用和使用使用自定义序列化器+反序列化器生成XML [英] SpringBoot: Consume & Produce XML with a Custom Serializer + Deserializer

查看:187
本文介绍了SpringBoot:使用和使用使用自定义序列化器+反序列化器生成XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有以下功能的SpringBoot服务:

I have a SpringBoot Service with:

型号

public class Payload {
    private final String id;

    public Payload(String id){
        this.id = id;
    }

    public String getId() {
        return this.id;
    }
}

控制器

@RestController
@RequestMapping("/payload")
public class PayloadController {

    @RequestMapping(method = RequestMethod.POST)
    public Payload post(@RequestBody final Payload payload) {
        return payload;
    }
}

我需要此Controller才能处理JSON& XML请求并以相同格式响应. 只要将Content-TypeAccept标头设置为正确的媒体类型,此方法就可以正常工作.

I need this Controller to be able to handle JSON & XML requests and respond with the same format. This works fine providing I set the Content-Type and Accept headers to the correct media types.

但是,我的XML有效负载的结构必须与JSON略有不同:

However, my XML payloads need to be in a subtly different structure to my JSON:

XML:

<Payload>
    <id value="some-value"/>
</Payload>

JSON:

{
    id: "some-value"
}

如何确保将id包裹在xml节点中,并将值"作为属性?

How do I ensure my id is wrapped in an xml node and has the "value" as an attribute?

我已经尝试在Payload类上使用@JsonSerialize@JsonDeserialize批注,但是当我这样做时,POST ing XML

I have tried using a @JsonSerialize and @JsonDeserialize annotation on my Payload class but as soon as I do this I get the following error when POSTing XML

{
    "timestamp": "2019-10-01T12:06:35.593+0000",
    "status": 415,
    "error": "Unsupported Media Type",
    "message": "Content type 'application/xml;charset=UTF-8' not supported",
    "path": "/payload"
}

推荐答案

您需要注册2个转换器:

You need to register 2 converters:

  1. org.springframework.http.converter.json.MappingJackson2HttpMessageConverter表示JSON.
  2. org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter表示XML.
  1. org.springframework.http.converter.json.MappingJackson2HttpMessageConverter for JSON.
  2. org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter for XML.

因为Payload类适合JSON有效负载,所以您只需添加JsonCreatorJsonProperty批注以使其起作用:

Because, Payload class fits JSON payload you need to add only JsonCreator and JsonProperty annotations to make it work:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Payload {

    private final String id;

    @JsonCreator
    public Payload(@JsonProperty(value = "id") String id) {
        this.id = id;
    }

    public String getId() {
        return this.id;
    }
}

XML有效负载在默认情况下不适合,因此我们需要实现自定义序列化程序:

XML payload does not fit by default, so we need to implement custom serialiser:

import com.example.demo.model.Payload;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;

import java.io.IOException;

public class PayloadXmlSerializer extends JsonSerializer<Payload> {

    @Override
    public void serialize(Payload value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        ToXmlGenerator toXmlGenerator = (ToXmlGenerator) gen;
        toXmlGenerator.writeStartObject();

        toXmlGenerator.writeObjectFieldStart("id");
        toXmlGenerator.setNextIsAttribute(true);
        toXmlGenerator.writeFieldName("value");
        toXmlGenerator.writeString(value.getId());
        toXmlGenerator.setNextIsAttribute(false);
        toXmlGenerator.writeEndObject();

        toXmlGenerator.writeEndObject();
    }
}

和反序列化器:

import com.example.demo.model.Payload;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.node.TextNode;

import java.io.IOException;

public class PayloadXmlDeserializer extends JsonDeserializer<Payload> {

    @Override
    public Payload deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        TreeNode root = p.readValueAsTree();
        TreeNode value = root.at(JsonPointer.compile("/id/value"));
        if (value.isMissingNode()) {
            return new Payload(null);
        }
        TextNode textNode = (TextNode)value;
        return new Payload(textNode.textValue());
    }
}

最后,我们需要在HTTP转换器和自定义序列化器/反序列化器上进行注册:

Finally, we need to register above HTTP converters and custom serialiser/deserialiser:

import com.example.demo.model.Payload;
import com.example.jackson.PayloadXmlDeserializer;
import com.example.jackson.PayloadXmlSerializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@EnableWebMvc
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        //JSON
        converters.add(new MappingJackson2HttpMessageConverter());

        // XML
        converters.add(new MappingJackson2XmlHttpMessageConverter(Jackson2ObjectMapperBuilder
                .xml()
                .modules(payloadModule())
                .build()));
    }

    public SimpleModule payloadModule() {
        SimpleModule module = new SimpleModule();
        module.addDeserializer(Payload.class, new PayloadXmlDeserializer());
        module.addSerializer(Payload.class, new PayloadXmlSerializer());

        return module;
    }
}

另请参阅:

  • Using Jackson to add XML attributes to manually-built node-tree
  • 415 Unsupported MediaType for POST request in spring application
  • Spring MVC

这篇关于SpringBoot:使用和使用使用自定义序列化器+反序列化器生成XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆