使用 Jackson 将 XML 属性添加到手动构建的节点树 [英] Using Jackson to add XML attributes to manually-built node-tree

查看:28
本文介绍了使用 Jackson 将 XML 属性添加到手动构建的节点树的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试设置代码以使用 Jackson 创建节点树,然后可以使用它来编写 JSONXML.我已经像这样手动创建了节点树:

I'm trying to set up code to create a node tree using Jackson which can then be used to write either JSON or XML. I've created the node tree manually like so:

XmlMapper nodeMapper = new XmlMapper();

ObjectNode rootNode = nodeMapper.createObjectNode();
ObjectNode currentNode = rootNode.putObject("Examples");
currentNode.put("Puppy", TRUE)
           .put("Apple", 2)
           .put("Jet", "Li");
currentNode = rootNode.putObject("Single");
currentNode.put("One", 1);

String writePath = "C:/users/itsameamario/Documents/basicXMLtest.xml";
nodeMapper.writeValue(new File(writePath), rootNode);

我的 XML 输出是:

My XML output is:

<?xml version="1.0"?>
<ObjectNode>
    <Examples>
        <Puppy>true</Puppy>
        <Apple>2</Apple>
        <Jet>Li</Jet>
    </Examples>
    <Single>
        <One>1</One>
    </Single>
</ObjectNode>

但是,对于 XML 的某些部分,我想向其中一个节点添加一个属性,如下所示:

However for some parts of the XML I would like to add an attribute to one of the nodes like so:

<Examples overlyComplicated="yes">
<!--...-->
</Examples>

我发现的所有包含属性的示例都应用于预先存在的类.我一直无法找到一种将属性添加到手动构建的节点树的方法,如上所述.使用 Jackson 是否可行?

All the examples I've found that include attributes are applied to a pre-existing class. I have been unable to find a method to add attributes to a manually-built node-tree as above. Is it doable using Jackson?

推荐答案

不可能将给定的属性标记为 attribute 因为 ObjectNode 对序列化一无所知.您可以为 POJO 类执行此操作,并且 com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator 仅在 @JacksonXmlProperty(isAttribute = true) 时才会处理它 注释用于给定的属性.我建议为需要属性的元素创建 POJO 并使用 Jackson XML 注释或实现 JsonSerializable 接口.它可能如下所示:

It is not possible to mark given property as attribute since ObjectNode does not know anything about the serialisation. You can do that for POJO class and com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator will handle it only if @JacksonXmlProperty(isAttribute = true) annotation is used for given property. I suggest to create POJO for element where you need attribute and use Jackson XML annotations or implement JsonSerializable interface. It could look like below:

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializable;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

public class XmlMapperApp {

    public static void main(String[] args) throws Exception {
        Map<String, Object> map = new LinkedHashMap<>();
        map.put("Puppy", Boolean.TRUE);
        map.put("Apple", 2);
        map.put("Jet", "Li");
        Examples examples = new Examples();
        examples.setOverlyComplicated("yes");
        examples.setMap(map);

        XmlMapper mapper = new XmlMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);

        ObjectNode rootNode = mapper.createObjectNode();
        rootNode.putPOJO("Examples", examples);
        ObjectNode currentNode = rootNode.putObject("Single");
        currentNode.put("One", 1);

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

class Examples implements JsonSerializable {

    @Override
    public void serialize(JsonGenerator gen, SerializerProvider serializers) throws IOException {
        ToXmlGenerator toXmlGenerator = (ToXmlGenerator) gen;
        toXmlGenerator.writeStartObject();

        writeAttributes(toXmlGenerator);
        writeMap(toXmlGenerator);

        toXmlGenerator.writeEndObject();
    }

    private void writeAttributes(ToXmlGenerator gen) throws IOException {
        if (overlyComplicated != null) {
            gen.setNextIsAttribute(true);
            gen.writeFieldName("overlyComplicated");
            gen.writeString(overlyComplicated);
            gen.setNextIsAttribute(false);
        }
    }

    private void writeMap(ToXmlGenerator toXmlGenerator) throws IOException {
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            toXmlGenerator.writeObjectField(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public void serializeWithType(JsonGenerator gen, SerializerProvider serializers, TypeSerializer typeSer) throws IOException {
        serialize(gen, serializers);
    }

    private String overlyComplicated;
    private Map<String, Object> map;

    // getters, setters, toString
}

以上代码打印:

<ObjectNode>
  <Examples overlyComplicated="yes">
    <Puppy>true</Puppy>
    <Apple>2</Apple>
    <Jet>Li</Jet>
  </Examples>
  <Single>
    <One>1</One>
  </Single>
</ObjectNode>

如果您想对 JSON 序列化使用相同的 Example POJO,您需要在 serialize 中处理它> 方法或创建另一个 ObjectNode 而不是 Examples 对象.

In case you want to use the same Example POJO for JSON serialisation you need to handle it in serialize method or create another ObjectNode instead of Examlples object.

这篇关于使用 Jackson 将 XML 属性添加到手动构建的节点树的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆