Java Jackson根据字段值添加包装器

Java Jackson根据字段值添加包装器,java,xml,serialization,jackson,xml-serialization,Java,Xml,Serialization,Jackson,Xml Serialization,我的课程如下: @JsonRootName("ASSETS") public class Assets{ String val1; String val2; } import com.fasterxml.jackson.annotation.JsonRootName; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; imp

我的课程如下:

@JsonRootName("ASSETS")
public class Assets{
    String val1;
    String val2;
}
import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;

import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class XmlMapperApp {

    public static void main(String[] args) throws Exception {
        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
        xmlMapper.setDefaultUseWrapper(false);

        Assets assets = new Assets();
        assets.getAssets().add(new Asset());
        assets.getAssets().add(new Asset());

        System.out.println(xmlMapper.writeValueAsString(assets));
    }
}

class AssetXMLSerializer extends JsonSerializer<Asset> {

    private final QName wrapper = new QName("val1_val2");
    @Override
    public void serialize(Asset value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        ToXmlGenerator xmlGen = (ToXmlGenerator) gen;

        xmlGen.writeStartObject();
        xmlGen.startWrappedValue(wrapper, wrapper);
        xmlGen.writeStringField("val1", value.getVal1());
        xmlGen.writeStringField("val2", value.getVal2());
        xmlGen.finishWrappedValue(wrapper, wrapper);
        xmlGen.writeEndObject();

    }
}

@JsonRootName("ASSETS")
class Assets {

    @JacksonXmlProperty(localName = "ASSET")
    private List<Asset> assets = new ArrayList<>();

    // getters, setters, toString
}

@JsonSerialize(using = AssetXMLSerializer.class)
class Asset {
    private String val1;
    private String val2;

    // getters, setters, toString
}
不幸的是,我需要将其序列化为以下内容:

<ASSETS>
   <ASSET>
      <val1_val2>
         <val1>x</val1>
         <val2>y</val2>
      </val1_val2>
   </ASSET>
   <ASSET>
      <val1_val2>
         <val1>x</val1>
         <val2>y</val2>
      </val1_val2>
   </ASSET>
</ASSETS>

x
Y
x
Y

我可以在
资产
中列出
资产
对象,但如何添加由两个字段组合而成的额外包装器?

您需要编写自定义序列化程序。为此,扩展
com.fasterxml.jackson.databind.JsonSerializer
class。另外,要创建额外的包裹元素,请使用方法。示例代码如下所示:

@JsonRootName("ASSETS")
public class Assets{
    String val1;
    String val2;
}
import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;

import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class XmlMapperApp {

    public static void main(String[] args) throws Exception {
        XmlMapper xmlMapper = new XmlMapper();
        xmlMapper.enable(SerializationFeature.INDENT_OUTPUT);
        xmlMapper.setDefaultUseWrapper(false);

        Assets assets = new Assets();
        assets.getAssets().add(new Asset());
        assets.getAssets().add(new Asset());

        System.out.println(xmlMapper.writeValueAsString(assets));
    }
}

class AssetXMLSerializer extends JsonSerializer<Asset> {

    private final QName wrapper = new QName("val1_val2");
    @Override
    public void serialize(Asset value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        ToXmlGenerator xmlGen = (ToXmlGenerator) gen;

        xmlGen.writeStartObject();
        xmlGen.startWrappedValue(wrapper, wrapper);
        xmlGen.writeStringField("val1", value.getVal1());
        xmlGen.writeStringField("val2", value.getVal2());
        xmlGen.finishWrappedValue(wrapper, wrapper);
        xmlGen.writeEndObject();

    }
}

@JsonRootName("ASSETS")
class Assets {

    @JacksonXmlProperty(localName = "ASSET")
    private List<Asset> assets = new ArrayList<>();

    // getters, setters, toString
}

@JsonSerialize(using = AssetXMLSerializer.class)
class Asset {
    private String val1;
    private String val2;

    // getters, setters, toString
}
另见:


  • 这管用!有没有处理大量字段的技巧?(而不是手动输入var1、var2等)虽然我不喜欢这个解决方案使用反射,但我真的很感谢您为我深入研究了这个问题,非常感谢!这救了我的命。@Steve,反射只用于生成包装名称。如果思考对这份工作来说太“强烈”,你可以用另一种方式来做。当我更仔细地阅读它时,我可以看到这一点。再次感谢,这是一个伟大的解决方案!