Java Jackson XML注释:从带有属性的XML元素中提取单个字符串值
我使用Jackson XML注释将XML文档从外部API转换为POJO。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
<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;
}