【问题标题】:How to configure Jackson XmlMapper to use data types from xml schema如何配置 Jackson XmlMapper 以使用来自 xml 模式的数据类型
【发布时间】:2018-11-14 07:01:09
【问题描述】:

我有一条 xml 消息需要转换为 json 消息格式。 xml 消息定义了包含元素类型信息的 xml 模式。但是,生成的 json 将所有值作为文本值而不是 xml 模式中提到的布尔值/数字。如何指示 XmlMapper() 从 xml 架构中派生类型信息?

XmlMapper xmlMapper = new XmlMapper();
String xmlMsg = getResourceContent("test.xml");        
JsonNode node = xmlMapper.readTree(xmlMsg.getBytes());
ObjectMapper jsonMapper = new ObjectMapper();
String json = jsonMapper.writeValueAsString(node);

示例 xml:

<myMessage>
     <id>333</id>
     <type>Text</type>
     <flag>true</flag>
</myMessage>

生成的 json:

{
  "id": "333",
  "type": "Text",
  "flag": "true"
}

预期的 json:

{
  "id": 333,
  "type": "Text",
  "flag": true
}

【问题讨论】:

    标签: json xml jackson2 jackson-databind


    【解决方案1】:

    如果您的 xml 架构很简单,将“true/false”转换为“boolean”并将“number”转换为“long”就足够了。我有一个解决方案。

    JsonNode node = xmlMapper.readTree(xmlMsg.getBytes()); 之后,node 的子代是TextNode 类型。您可以旅行node对象,如果值满足某些条件,则将TextNode转换为BooleanNodeLongNode

    添加以下方法:

    public static JsonNode resolveType(JsonNode jsonNode) {
        if (jsonNode instanceof ObjectNode) {
            ObjectNode objectNode = (ObjectNode) jsonNode;
            Iterator<Entry<String, JsonNode>> fields = objectNode.fields();
            while (fields.hasNext()) {
                Entry<String, JsonNode> next = fields.next();
                next.setValue(resolveType(next.getValue()));
            }
        } else if (jsonNode instanceof TextNode) {
            TextNode textNode = (TextNode) jsonNode;
            String value = textNode.textValue();
            if ("true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value)) {
                jsonNode = BooleanNode.valueOf(Boolean.valueOf(value));
            } else if (StringUtils.isNumeric(value)) {
                jsonNode = LongNode.valueOf(Long.valueOf(value));
            }
        }
        return jsonNode;
    }
    

    然后用这个方法解析JsonNode node的类型:

    JsonNode node = xmlMapper.readTree(xmlMsg.getBytes());
    node = resolveType(node); // <--- Add this statement to your code.
    ObjectMapper jsonMapper = new ObjectMapper();
    //...
    

    输出应该是预期的 json:

    {"id":333,"type":"Text","flag":true}

    【讨论】:

    • 我授予了这个答案,因为它比第一个答案更接近我的需要。我想我可以使用这种方法作为基础,并从模式中提取哪个字段属于哪个类型的信息。猜测类型也不行,因为有些字段满足数字检查但应该作为字符串导入。
    【解决方案2】:

    我创建了 POJO 类,并在 Message.java 中声明了我的数据类型:

    public class Message {
        private Integer id;
        private String type;
        private Boolean flag;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getType() {
            return type;
        }
    
        public void setType(String type) {
            this.type = type;
        }
    
        public Boolean getFlag() {
            return flag;
        }
    
        public void setFlag(Boolean flag) {
            this.flag = flag;
        }
    }
    

    在你的代码中:

    //src the XML String to Parse
    XmlMapper xmlMapper = new XmlMapper();
    Message myMessage = xmlMapper.readValue(src, Message.class);
    
    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(myMessage);
    
    System.out.println(json);
    

    结果是:

    {"id":333,"type":"Text","flag":true}
    

    【讨论】:

    • 是的,使用 POJO 当然我可以这样做,但是我有通用 XML,所以我不想拥有 POJO,因为我不想在 POJO 中再次关心它们的结构,我已经定义了他们的架构。我需要在 XML 和通用 JSON 对象之间进行直接转换,并确保它们包含正确的数据类型。
    • 不知何故有人应该将字符串转换为布尔值。因为truefalse 可能只是短信。所以,你需要创建 POJO 类,并明确声明它是布尔对象。
    • 这对我来说没有意义。 xml架构中包含哪个属性属于哪个数据类型的信息,那么为什么要重复信息呢?正如我所说,我不需要 POJO,我也不想要 POJO:额外代码是额外的工作,是额外的维护等等......等等......原始问题也不包括 POJO。使用 POJO 的解决方案很简单。
    • 抱歉,您没有在问题描述中提到没有 POJO。之后,如果我们查看stackify.com/java-xml-jackson,请参阅部分 - Jackson XML 模块的限制。所以,没有 POJO 就没有办法解决你的问题。
    • 恕我直言,这个问题清楚地表明目标类型是JsonNode。 id 没有提到除此之外的任何 POJO。
    猜你喜欢
    • 2013-06-17
    • 1970-01-01
    • 2023-03-09
    • 2019-06-24
    • 2014-10-22
    • 1970-01-01
    • 2020-03-15
    • 2015-09-29
    • 2023-03-10
    相关资源
    最近更新 更多