Java Jackson XML注释:从带有属性的XML元素中提取单个字符串值

Java Jackson XML注释:从带有属性的XML元素中提取单个字符串值,java,xml,jackson,pojo,Java,Xml,Jackson,Pojo,我使用Jackson XML注释将XML文档从外部API转换为POJO。XML中的一个元素给我带来了一些麻烦。大多数元素没有属性,只有一个文本值,例如: <title>Title Here</title> 但这会导致以下错误: Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of Item: no String-argument con

我使用Jackson XML注释将XML文档从外部API转换为POJO。XML中的一个元素给我带来了一些麻烦。大多数元素没有属性,只有一个文本值,例如:

<title>Title Here</title>
但这会导致以下错误:

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not construct 
instance of Item: no String-argument constructor/factory method to deserialize from 
String value ('Security')
at [Source: java.io.ByteArrayInputStream@328ff654; line: 40, column: 21] 
“Security”是一个称为“tags”的xml属性的文本,该属性稍后会出现在文档中

我尝试进行以下更改,这消除了异常,但导致我在POJO中得到一个空值

public class Item {
    @JacksonXmlProperty(localName = "urgency")
    @JacksonXmlText
    private String urgency;
}
我觉得我错过了一些明显的东西。使用Jackson将此元素的文本转换为POJO上的字符串字段的最佳方式是什么

下面是我正在使用的完整类和XML文档

XML:

现在开始上课。为简洁起见,省略了getter和setter。还有一个Location、Destination和Category类,但除非有必要,否则我不会包含它们

根类:

@JacksonXmlRootElement(localName = "rss")
public class FeedRoot {
    @JacksonXmlProperty(localName = "channel")
    private FeedChannel channel;
}
频道类别:

public class FeedChannel {
    @JacksonXmlElementWrapper(localName = "item", useWrapping = false)
    @JacksonXmlProperty(localName = "item")
    private List<Item> items;
}

更新

由于OP是在我的回答之后更新的,我添加了一些考虑

即使使用提供的代码,如果我只尝试反序列化Item元素,一切都很好

当涉及到所有rss元素时,问题就出现了

从XML的角度看,问题在于FeedChannel的定义

public class FeedChannel {
    @JacksonXmlElementWrapper(localName = "item", useWrapper = false)
    @JacksonXmlProperty(localName = "item")
    private List<Item> items;
}
以下是测试:

public class ItemTest {

    @Test
    public void readItemTest() {

        final String itemXml = "<item>\n" +
                "    <field1>Field1 Text</field1>\n" +
                "    <field2>Field2 Text</field2>\n" +
                "    <urgency id=\"UrgCaution\">Caution</urgency>\n" +
                "    <tags>tag</tags>\n" +
                "</item>";

        XmlMapper xm = new XmlMapper();

        try {
            Item myItem = xm.readValue(itemXml, Item.class);

            assert("Caution".equals(myItem.getUrgency()));
        } catch (IOException e) {
            e.printStackTrace();
            assert(false);
        }

    }
}
公共类ItemTest{
@试验
public void readItemTest(){
最终字符串itemXml=“\n”+
“字段1文本\n”+
“字段2文本\n”+
“注意\n”+
“标记\n”+
"";
XmlMapper xm=新的XmlMapper();
试一试{
Item myItem=xm.readValue(itemXml,Item.class);
断言(“Caution.equals(myItem.geturrency());
}捕获(IOE异常){
e、 printStackTrace();
断言(假);
}
}
}
没有错误,没有问题,它只是按预期工作

爪哇7

我的依赖项:

   <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.8.0</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.8.0</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.8.0</version>
    </dependency>

com.fasterxml.jackson.core
杰克逊核心
2.8.0
com.fasterxml.jackson.core
杰克逊注释
2.8.0
com.fasterxml.jackson.dataformat
jackson数据格式xml
2.8.0
要有这个

<urgency id="UrgCaution">Caution</urgency>

我认为@JacksonXmlText是不正确的。也许您必须提供POJO中的所有属性。您是指剩余的xml元素吗?如果是的话,我已经在做了。好奇。我将编辑主要帖子,以包含完整的XML文档和所有注释。@请在我回答后更新OP。没问题,我已经更新了。谢谢你的更新。因为我无法更改XML,所以这似乎是我必须解决的问题。@您可以尝试为item属性定义自定义反序列化程序。这应该是可行的,但更多的是代码。
"Could not read document: Can not construct instance of 
com.namespacestuff.Item: no String-argument constructor/factory 
method to deserialize from String value ('Railway disruptions')\n at 
[Source: java.io.ByteArrayInputStream@45563ea1; line: 42, column: 32] 
(through reference chain: com.namespacestuff.FeedRoot[\"channel\"]-
>com.namespacestuff.FeedChannel[\"item\"]->java.util.ArrayList[5]); 
nested exception is 
com.fasterxml.jackson.databind.JsonMappingException: Can not 
construct instance of com.namespacestuff.Item: no String-argument 
constructor/factory method to deserialize from String value ('Railway 
disruptions')\n at [Source: java.io.ByteArrayInputStream@45563ea1; 
line: 42, column: 32] (through reference chain: 
com.namespacestuff.FeedRoot[\"channel\"]-
>com.namespacestuff.FeedChannel[\"item\"]->java.util.ArrayList[5])"
public class FeedChannel {
    @JacksonXmlElementWrapper(localName = "item", useWrapper = false)
    @JacksonXmlProperty(localName = "item")
    private List<Item> items;
}
<items><item>...</item></items>
@JacksonXmlRootElement(localName = "item")
public class Item {
    @JacksonXmlProperty(localName = "field1")
    private String field1;

    @JacksonXmlProperty(localName = "field2")
    private String field2;

    @JacksonXmlProperty(localName = "urgency")
    private String urgency;

    @JacksonXmlProperty(localName = "tags")
    private String tags;

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public String getField2() {
        return field2;
    }

    public void setField2(String field2) {
        this.field2 = field2;
    }

    public String getUrgency() {
        return urgency;
    }

    public void setUrgency(String urgency) {
        this.urgency = urgency;
    }

    public String getTags() {
        return tags;
    }

    public void setTags(String tags) {
        this.tags = tags;
    }
}
public class ItemTest {

    @Test
    public void readItemTest() {

        final String itemXml = "<item>\n" +
                "    <field1>Field1 Text</field1>\n" +
                "    <field2>Field2 Text</field2>\n" +
                "    <urgency id=\"UrgCaution\">Caution</urgency>\n" +
                "    <tags>tag</tags>\n" +
                "</item>";

        XmlMapper xm = new XmlMapper();

        try {
            Item myItem = xm.readValue(itemXml, Item.class);

            assert("Caution".equals(myItem.getUrgency()));
        } catch (IOException e) {
            e.printStackTrace();
            assert(false);
        }

    }
}
   <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.8.0</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.8.0</version>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>2.8.0</version>
    </dependency>
<urgency id="UrgCaution">Caution</urgency>
@JacksonXmlRootElement(localName = "urgency")
public class Urgency {
    @JacksonXmlProperty(isAttribute=true)
    String id;
    @JacksonXmlText
    String text;
}