java jackson xml 反序列化内联数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13179920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 11:47:02  来源:igfitidea点击:

Hymanson xml deserialize inline array

javaxmlarraysHymansondeserialization

提问by mailwurf

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).

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

<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>

My entities are

我的实体是

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 {
    @HymansonXmlProperty(isAttribute = true)
    public String name;

    @HymansonXmlText
    public String value;
}

@HymansonXmlRootElement
public class Parent {
    @HymansonXmlProperty(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. Alternative

1. 替代

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"])'

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

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...

我不想要一个简单的字符串列表。我需要两个:名称和值。所以我想到了Map<String, String>通过创建自己的反序列化器来使用 a 的想法......

2. Alternative

2. 替代

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

错误似乎是方法 PropDeser.deserialize()?consumes the结束标签。

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

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

是否有可能在XML 流中向后迭代?该方法如何知道何时停止?我没有任何线索。

回答by StaxMan

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

应该可以使用 Hymanson XML 模块 2.1 处理“解包”样式的列表元素,使用@HymansonXmlElementWrapper(useWrapping=false).

Structure should be something like this:

结构应该是这样的:

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

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

  public String description;

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

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

  public String value;
}

so your solution was quite close.

所以你的解决方案非常接近。

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.

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