杰克逊xml反序列化内联数组 [英] jackson xml deserialize inline array

查看:97
本文介绍了杰克逊xml反序列化内联数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何反序列化这种奇怪的XML.在我看来,缺少道具实体(在道具周围),但是我无法更改此XML(Web服务)的来源.

How to deserialize such strange XML. In my opinion, the props-entity is missing (around the props), but I can't change the source of this XML (a web service).

<parents>
  <parent name="first">
    <description><![CDATA[Description for the first-Entity]]></description>
    <prop name="level">
      <value><![CDATA[1]]></value>
    </prop>
    <prop name="enabled">
      <value><![CDATA[true]]></value>
    </prop>
    <prop name="version">
      <value><![CDATA[1.0-beta3]]></value>
    </prop>
  </parent>
  <parent name="second">...</parent>
  ...
</parents>

我的实体是

public class Test {
    @Test
    public void deserializerTest() throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper om = new XmlMapper();
        List<Parent> xml = om.readValue(new File("./test.xml"),
            new TypeReference<List<Parent>>() {});
    }
}

public class Prop {
    @JacksonXmlProperty(isAttribute = true)
    public String name;

    @JacksonXmlText
    public String value;
}

@JacksonXmlRootElement
public class Parent {
    @JacksonXmlProperty(isAttribute = true)
    public String name;

    public String description;

    // 1. alternative with List
    public List<Prop> prop;

    // 2. alternative with Map
    @JsonDeserialize(using = PropDeser.class)
    public Map<String, String> prop;
} 


public static class PropDeser extends JsonDeserializer<Map<String, String>> {

    @Override
    public Map<String, String> deserialize(JsonParser jp,
            DeserializationContext ctxt) throws IOException,
            JsonProcessingException {
        Map<String, String> ret = new HashMap<String, String>();
        boolean eof = false;
        while (jp.hasCurrentToken()) {
            JsonToken t = jp.getCurrentToken();
            switch (t) {
            case END_OBJECT:
                if (eof) {
                    return ret;
                }
                eof = true;
                break;
            case VALUE_STRING:
                ret.put(jp.getCurrentName(), jp.getText());
                break;
            default:
                eof = false;
                break;
            }
            jp.nextValue();
        }
        return null;
    }

}

1.替代

创建一个异常'无法实例化JSON字符串中的类型[简单类型,类my.test.Prop]的值;没有单字符串构造函数/工厂方法(通过引用链:my.test.Parent ["prop"])'

1. Alternative

creates an exception 'Can not instantiate value of type [simple type, class my.test.Prop] from JSON String; no single-String constructor/factory method (through reference chain: my.test.Parent["prop"])'

我不想要一个简单字符串列表.我需要:名字和价值.因此我想到了通过创建自己的解串器来使用Map<String, String>的想法...

I don't want a simple-String list. I need both: name and value. So I came to the idea of using a Map<String, String> by creating my own deserializer...

错误似乎是方法PropDeser.deserialize()消耗了父项的关闭标记.

The error seems to be method PropDeser.deserialize() consumes the closing-tag of the parent.

java.lang.NullPointerException
at com.fasterxml.jackson.databind.deser.impl.BeanPropertyMap.find(BeanPropertyMap.java:160)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:287)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:112)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:226)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:203)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:23)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2575)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1766)
at my.test.Test.deserializerTest(Test.java:57)

是否有可能在 XML流中向后迭代?该方法如何知道何时停止?我不知道.

Is there a possibility to iterate backward in the XML-stream? How can the method know when to stop? I have no clue.

推荐答案

应该可以使用@JacksonXmlElementWrapper(useWrapping=false)的Jackson XML模块2.1处理列表元素的未包装"样式.

It should be possible to handle "unwrapped" style of list elements with Jackson XML module 2.1, with @JacksonXmlElementWrapper(useWrapping=false).

结构应如下所示:

@JacksonXmlRootElement(localName="parents")
public class Parents {
  @JacksonXmlElementWrapper(useWrapping=false)
  public List<Parent> parent;
}

public class Parent {
  @JacksonXmlProperty(isAttribute=true)
  public String name;

  public String description;

  @JacksonXmlElementWrapper(useWrapping=false)
  public List<Prop> prop;
}

public class Prop {
  @JacksonXmlProperty(isAttribute=true)
  public String name;

  public String value;
}

所以您的解决方案非常接近.

so your solution was quite close.

请注意,如果使用内部类,则它们在声明中需要具有静态". 我用2.1.4进行了测试,它对我有用.

Note that if inner classes are used, they need to have 'static' in declaration. I tested this with 2.1.4, and it works for me.

这篇关于杰克逊xml反序列化内联数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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