使用Jackson将Java列表序列化为XML和JSON
在我基于Restlet的API中,使用Restlet-Jackson扩展,我试图将Java对象序列化为XML和JSON,但无法使用嵌套列表或多维数组获得我期望的格式(现有API已经发布) 以下是生成正确JSON的POJO:使用Jackson将Java列表序列化为XML和JSON,java,json,xml,jackson,restlet,Java,Json,Xml,Jackson,Restlet,在我基于Restlet的API中,使用Restlet-Jackson扩展,我试图将Java对象序列化为XML和JSON,但无法使用嵌套列表或多维数组获得我期望的格式(现有API已经发布) 以下是生成正确JSON的POJO: @JacksonXmlRootElement( localName = "table") @JsonInclude( JsonInclude.Include.NON_NULL) public class TableResponse { protected List da
@JacksonXmlRootElement( localName = "table")
@JsonInclude( JsonInclude.Include.NON_NULL)
public class TableResponse {
protected List data;
protected String[] columns;
public TableResponse( String[] columns, List<List<String>> data ) {
this.columns = columns;
this.data = data;
}
@JacksonXmlElementWrapper(localName = "data")
@JacksonXmlProperty(localName = "row")
//@CanIAddSomeAnnotationHereForNestedListElements?
public List<List<String>> getData() {
return data;
}
@JacksonXmlElementWrapper(localName = "columns")
@JacksonXmlProperty(localName = "column")
public String[] getColumns() {
return columns;
}
}
我希望能够像这样生成XML:
{
"data": [
[
"Row 1 Cell A",
"Row 1 Cell B"
],
[
"Row 2 Cell A",
"Row 2 Cell B"
],
[
"Row 3 Cell A",
"Row 3 Cell B"
]
],
"columns": [
"Column 1",
"Column 2"
]
}
<table>
<data>
<row>
<value>Row 1 Cell A</value>
<value>Row 1 Cell B</value>
</row>
<row>
<value>Row 2 Cell A</value>
<value>Row 2 Cell B</value>
</row>
<row>
<value>Row 3 Cell A</value>
<value>Row 3 Cell B</value>
</row>
</data>
<columns>
<column>Column 1</column>
<column>Column 2</column>
</columns>
</table>
我的项目中的一些依赖项包括:
- dataformat:jackson-dataformat-xml:2.5.3
- org.restlet.jee:org.restlet:2.3.5
- org.restlet.jee:org.restlet.ext.jackson:2.3.5
- org.restlet.jee:org.restlet.ext.json:2.3.5
顺便说一句,我在中也尝试了这个建议,但没有让我的XmlAdapter/@XmlJavaTypeAdapter在这里与restlet一起使用。仅使用Jackson注释似乎很难处理这两种格式。对于您的用例,我认为您需要实现一个单独处理JSON和XML的自定义序列化程序 此序列化程序如下所示:
public class TableResponseSerializer extends StdSerializer<TableResponse> {
private MediaType mediaType;
public TableResponseSerializer(MediaType mediaType) {
super(TableResponse.class);
this.mediaType = mediaType;
}
private void serializeJson(TableResponse swe,
JsonGenerator jgen,
SerializerProvider sp) throws IOException, JsonGenerationException {
(...)
}
private void serializeXml(TableResponse swe,
JsonGenerator jgen,
SerializerProvider sp) throws IOException, JsonGenerationException {
(...)
}
@Override
public void serialize(TableResponse swe,
JsonGenerator jgen,
SerializerProvider sp) throws IOException, JsonGenerationException {
if (mediaType.equals(MediaType.APPLICATION_JSON)) {
serializeJson(swe, jgen, sp);
} else if (mediaType.equals(MediaType.TEXT_XML)) {
serializeXml(swe, jgen, sp);
}
}
}
然后是CustomJacksonConverter
类,该类将在必要时使用这种表示:
public class CustomJacksonConverter extends JacksonConverter {
protected <T> JacksonRepresentation<T> create(MediaType mediaType, T source) {
return new CustomJacksonRepresentation<T>(mediaType, source);
}
protected <T> JacksonRepresentation<T> create(Representation source,
Class<T> objectClass) {
return new CustomJacksonRepresentation<T>(source, objectClass);
}
}
这样,您将根据内容协商(
Accept
header)获得XML和JSON所需的输出内容。我习惯于处理GSON以创建JSON字符串,因此我只能就此发言。根据我的经验,我不得不对各种数据类型进行大量实验,以获得我想要的数据,并发现HashMaps或LinkedHashMaps以及ArrayList的组合效果最好。您可能需要对这些进行实验,以查看jackson的结果。嗨,Thierry,我能问一下如何强制Restlet使用XStream而不是jackson吗?
{
"data": [
{
"values": [
"Row 1 Cell A",
"Row 1 Cell B"
]
},
{
"values": [
"Row 2 Cell A",
"Row 2 Cell B"
]
},
{
"values": [
"Row 3 Cell A",
"Row 3 Cell B"
]
}
],
"columns": [
"Column 1",
"Column 2"
]
}
public class TableResponseSerializer extends StdSerializer<TableResponse> {
private MediaType mediaType;
public TableResponseSerializer(MediaType mediaType) {
super(TableResponse.class);
this.mediaType = mediaType;
}
private void serializeJson(TableResponse swe,
JsonGenerator jgen,
SerializerProvider sp) throws IOException, JsonGenerationException {
(...)
}
private void serializeXml(TableResponse swe,
JsonGenerator jgen,
SerializerProvider sp) throws IOException, JsonGenerationException {
(...)
}
@Override
public void serialize(TableResponse swe,
JsonGenerator jgen,
SerializerProvider sp) throws IOException, JsonGenerationException {
if (mediaType.equals(MediaType.APPLICATION_JSON)) {
serializeJson(swe, jgen, sp);
} else if (mediaType.equals(MediaType.TEXT_XML)) {
serializeXml(swe, jgen, sp);
}
}
}
private void serializeJson(TableResponse swe,
JsonGenerator jgen,
SerializerProvider sp) throws IOException, JsonGenerationException {
jgen.writeStartObject();
// Data
jgen.writeArrayFieldStart("data");
for (List<String> row : swe.getData()) {
jgen.writeStartArray();
for (String rowElt : row) {
jgen.writeString(rowElt);
}
jgen.writeEndArray();
}
jgen.writeEndArray();
// Columns
jgen.writeArrayFieldStart("columns");
for (String column : swe.getColumns()) {
jgen.writeString(column);
}
jgen.writeEndArray();
jgen.writeEndObject();
}
private void serializeXml(TableResponse swe,
JsonGenerator jgen,
SerializerProvider sp) throws IOException, JsonGenerationException {
jgen.writeStartObject();
// Data
jgen.writeObjectFieldStart("data");
jgen.writeArrayFieldStart("row");
for (List<String> row : swe.getData()) {
jgen.writeStartObject();
jgen.writeArrayFieldStart("value");
for (String rowElt : row) {
jgen.writeString(rowElt);
}
jgen.writeEndArray();
jgen.writeEndObject();
}
jgen.writeEndArray();
jgen.writeEndObject();
// Columns
jgen.writeObjectFieldStart("columns");
jgen.writeArrayFieldStart("column");
for (String column : swe.getColumns()) {
jgen.writeString(column);
}
jgen.writeEndArray();
jgen.writeEndObject();
jgen.writeEndObject();
}
public class CustomJacksonRepresentation<T> extends JacksonRepresentation<T> {
public CustomJacksonRepresentation(MediaType mediaType, T object) {
super(mediaType, object);
}
public CustomJacksonRepresentation(Representation representation,
Class<T> objectClass) {
super(representation, objectClass);
}
public CustomJacksonRepresentation(T object) {
super(object);
}
@Override
protected ObjectMapper createObjectMapper() {
ObjectMapper objectMapper = super.createObjectMapper();
if (getObjectClass().equals(TableResponse.class)) {
SimpleModule mod = new SimpleModule("");
mod.addSerializer(new TableResponseSerializer(getMediaType()));
objectMapper.registerModule(mod);
}
return objectMapper;
}
}
public class CustomJacksonConverter extends JacksonConverter {
protected <T> JacksonRepresentation<T> create(MediaType mediaType, T source) {
return new CustomJacksonRepresentation<T>(mediaType, source);
}
protected <T> JacksonRepresentation<T> create(Representation source,
Class<T> objectClass) {
return new CustomJacksonRepresentation<T>(source, objectClass);
}
}
List<ConverterHelper> converters = Engine.getInstance().getRegisteredConverters();
JacksonConverter jacksonConverter = new JacksonConverter();
for (ConverterHelper converter : converters) {
if (converter instanceof JacksonConverter) {
jacksonConverter = (JacksonConverter) converter;
break;
}
}
if (jacksonConverter!=null) {
converters.remove(jacksonConverter);
converters.add(new CustomJacksonConverter());
}