【问题标题】:SpringBoot: Consume & Produce XML with a Custom Serializer + DeserializerSpring Boot:使用自定义序列化器 + 反序列化器消费和生成 XML
【发布时间】:2020-01-30 17:24:22
【问题描述】:

我有一个 SpringBoot 服务:

型号

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;
    }
}

我需要这个控制器能够处理 JSON 和 XML 请求并以相同的格式响应。 如果我将 Content-TypeAccept 标头设置为正确的媒体类型,这可以正常工作。

但是,我的 XML 有效负载的结构需要与我的 JSON 稍有不同:

XML:

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

JSON:

{
    id: "some-value"
}

我如何确保我的id 被包装在一个 xml 节点中并具有“值”作为属性?


我曾尝试在我的Payload 类上使用@JsonSerialize@JsonDeserialize 注释,但一旦我这样做,当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"
}

【问题讨论】:

    标签: java spring-boot jackson jackson-dataformat-xml


    【解决方案1】:

    您需要注册2个转换器:

    1. org.springframework.http.converter.json.MappingJackson2HttpMessageConverterJSON
    2. org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverterXML

    因为Payload 类适合JSON 有效负载,您只需添加JsonCreatorJsonProperty 注释即可使其工作:

    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;
        }
    }
    

    XMLpayload 默认不适合,所以我们需要实现自定义序列化器:

    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转换器和自定义序列化器/反序列化器:

    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;
        }
    }
    

    另见:

    【讨论】:

      猜你喜欢
      • 2022-07-21
      • 2019-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-31
      • 1970-01-01
      • 2018-02-19
      • 1970-01-01
      • 2020-05-27
      相关资源
      最近更新 更多