问题描述
我有一个 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;
}
}
我需要这个控制器来处理 JSON &XML 请求并以相同的格式响应.如果我将 Content-Type
和 Accept
标头设置为正确的媒体类型,这可以正常工作.
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 POST
ing 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个转换器:
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
用于JSON
.org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter
用于XML
.
org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
forJSON
.org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter
forXML
.
因为 Payload
类适合 JSON
有效负载,您只需要添加 JsonCreator
和 JsonProperty
注释即可工作:
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
payload 默认不适合,所以我们需要实现自定义序列化器:
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;
}
}
另见:
这篇关于SpringBoot:消费 &使用自定义序列化器 + 反序列化器生成 XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!