Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 带Jackson的动态根元素_Java_Xml_Jackson_Xml Serialization_Jackson Dataformat Xml - Fatal编程技术网

Java 带Jackson的动态根元素

Java 带Jackson的动态根元素,java,xml,jackson,xml-serialization,jackson-dataformat-xml,Java,Xml,Jackson,Xml Serialization,Jackson Dataformat Xml,我目前正在从事一个项目,该项目处理的元素(出于遗留原因)必须具有表示其类型的标记名 基本上我有: @JsonRootName(“节点”) 类节点文档{ 私有字符串类型; } 其输出类似于: 但我们所期望的是: @JsonRootName在方法或属性上似乎不可用 即使有SerializationConfig.WithRoName()或自定义序列化程序,我似乎也找不到用存储在对象本身中的动态值定义根名称的方法。我假设NodeDocument包含不止一个属性。在这种情况下,您需要与BeanS

我目前正在从事一个项目,该项目处理的元素(出于遗留原因)必须具有表示其类型的标记名

基本上我有:

@JsonRootName(“节点”)
类节点文档{
私有字符串类型;
}
其输出类似于:


但我们所期望的是:


@JsonRootName
在方法或属性上似乎不可用


即使有
SerializationConfig.WithRoName()
或自定义序列化程序,我似乎也找不到用存储在对象本身中的动态值定义根名称的方法。

我假设
NodeDocument
包含不止一个属性。在这种情况下,您需要与
BeanSerializerModifier
一起实现自定义serialiser,它允许您序列化所有属性。下面的代码显示了完整的解决方案:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import com.fasterxml.jackson.databind.util.NameTransformer;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;

import javax.xml.namespace.QName;
import java.io.IOException;
import java.util.Objects;

public class XmlJacksonApp {

    public static void main(String... args) throws Exception {
        SimpleModule dynamicRootNameModule = new SimpleModule();
        dynamicRootNameModule.setSerializerModifier(new DynamicRootNameBeanSerializerModifier());

        XmlMapper mapper = XmlMapper.xmlBuilder()
                .enable(SerializationFeature.INDENT_OUTPUT)
                .addModule(dynamicRootNameModule)
                .build();
        NodeDocument element = new NodeDocument();
        element.setId(123);
        element.setName("Rick and Morty.doc");
        element.setType("sitcom");

        mapper.writeValue(System.out, element);
    }
}

class DynamicRootNameBeanSerializerModifier extends BeanSerializerModifier {
    @Override
    public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
        if (beanDesc.getBeanClass() == NodeDocument.class) {
            return new NodeDocumentJsonSerializer((JsonSerializer<NodeDocument>) serializer);
        }
        return super.modifySerializer(config, beanDesc, serializer);
    }
}

class NodeDocumentJsonSerializer extends JsonSerializer<NodeDocument> {
    private final JsonSerializer<NodeDocument> serializer;

    NodeDocumentJsonSerializer(JsonSerializer<NodeDocument> serializer) {
        this.serializer = Objects.requireNonNull(serializer);
    }

    @Override
    public void serialize(NodeDocument value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        ToXmlGenerator xmlGen = (ToXmlGenerator) gen;
        writeDynamicRootName(value.getType(), xmlGen);
        serializeProperties(value, gen, serializers);
        writeEndObject(xmlGen);
    }

    private void writeDynamicRootName(String rootName, ToXmlGenerator xmlGen) throws IOException {
        xmlGen.setNextName(new QName("", rootName));
        xmlGen.writeStartObject();
    }

    private void serializeProperties(NodeDocument value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        serializer.unwrappingSerializer(NameTransformer.NOP).serialize(value, gen, serializers);
    }

    private void writeEndObject(ToXmlGenerator xmlGen) throws IOException {
        xmlGen.writeEndObject();
    }
}

class NodeDocument {

    @JsonIgnore
    private String type;
    private int id;
    private String name;

    // getters, setters
}
import com.fasterxml.jackson.annotation.JsonIgnore;
导入com.fasterxml.jackson.core.JsonGenerator;
导入com.fasterxml.jackson.databind.BeanDescription;
导入com.fasterxml.jackson.databind.JsonSerializer;
导入com.fasterxml.jackson.databind.SerializationConfig;
导入com.fasterxml.jackson.databind.SerializationFeature;
导入com.fasterxml.jackson.databind.SerializerProvider;
导入com.fasterxml.jackson.databind.module.SimpleModule;
导入com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
导入com.fasterxml.jackson.databind.util.NameTransformer;
导入com.fasterxml.jackson.dataformat.xml.XmlMapper;
导入com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
导入javax.xml.namespace.QName;
导入java.io.IOException;
导入java.util.Objects;
公共类XmlJacksonApp{
公共静态void main(字符串…参数)引发异常{
SimpleModule dynamicRootNameModule=新SimpleModule();
dynamicRootNameModule.setSerializerModifier(新的DynamicRootNameBeanSerializerModifier());
XmlMapper mapper=XmlMapper.xmlBuilder()
.enable(SerializationFeature.INDENT_输出)
.addModule(dynamicRootNameModule)
.build();
NodeDocument元素=新的NodeDocument();
元素setId(123);
元素集合名(“Rick and Morty.doc”);
元素集类型(“情景喜剧”);
mapper.writeValue(System.out,element);
}
}
类DynamicRootNameBeanSerializerModifier扩展了BeanSerializerModifier{
@凌驾
公共JsonSerializer修改序列化程序(SerializationConfig配置、BeanDescription beanDesc、JsonSerializer序列化程序){
if(beanDesc.getBeanClass()==NodeDocument.class){
返回新的NodeDocumentJsonSerializer((JsonSerializer)序列化程序);
}
返回super.modifySerializer(config、beanDesc、serializer);
}
}
类NodeDocumentJsonSerializer扩展了JsonSerializer{
私有最终JsonSerializer序列化程序;
NodeDocumentJsonSerializer(JsonSerializer序列化程序){
this.serializer=Objects.requirennull(序列化程序);
}
@凌驾
public void serialize(NodeDocument值、JsonGenerator gen、SerializerProvider序列化程序)引发IOException{
ToXmlGenerator xmlGen=(ToXmlGenerator)gen;
writeDynamicRootName(value.getType(),xmlGen);
序列化属性(值、根、序列化器);
写入对象(xmlGen);
}
私有void writeDynamicRootName(字符串rootName,ToXmlGenerator xmlGen)引发IOException{
setNextName(新的QName(“,rootName));
xmlGen.writeStartObject();
}
私有void serializeProperties(NodeDocument值、JsonGenerator gen、SerializerProvider序列化程序)引发IOException{
反包装序列化程序(NameTransformer.NOP).serialize(value,gen,serializer);
}
私有void writeEndObject(ToXmlGenerator xmlGen)引发IOException{
xmlGen.writeEndObject();
}
}
类节点文档{
@杰索尼奥雷
私有字符串类型;
私有int-id;
私有字符串名称;
//能手,二传手
}
以上代码打印:

<sitcom>
  <id>123</id>
  <name>Rick and Morty.doc</name>
</sitcom>

123
瑞克和莫蒂

假设您可以轻松地切换/配置映射器一个脏的、不太可配置但仍然非常简单的方法是覆盖
XmlMapper
,如:

@SuppressWarnings("serial")
public class MyXmlMapper extends XmlMapper {
    @Override
    public String writeValueAsString(Object value) throws JsonProcessingException {
        String xml = super.writeValueAsString(value);
        if(value instanceof NodeDocument) {
            return xml.replaceAll("NodeDocument", ((NodeDocument)value).getType());
        }
        return xml;
    }
}

无论如何都不是一个完美的解决方案,也可能不适用于所有情况,但作为一个选项的示例,可根据情况进行更改。

请查看以下答案:。您需要使用
ToXmlGenerator
类和
setNextName
方法实现自定义序列化程序并从给定实例设置根名称;我不知道
setNextName
,但是有没有什么工具可以避免序列化对象属性所需的所有样板代码?