2017-04-26 18 views
1

私はジャクソンXMLアノテーションを使用して、XML文書を外部APIからPOJOに変換しています。 XMLの1つの要素が私に少し問題を与えています。要素のほとんどは属性を持っていない、とだけテキスト値など:ジャクソンXMLアノテーション:XML要素から属性を持つ単一文字列値を抽出

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

I:

<title>Title Here</title> 

私はこのような属性を持っているけれども一つの要素、といくつかの問題を抱えていますテキスト値 "Caution"を取り出して文字列に格納したいだけです。私はもともと私のJavaクラスでは、この方法を試してみました:

public class Item { 
    @JacksonXmlProperty(localName = "urgency") 
    private String urgency; 
} 

しかし、それは、次のエラーが発生:

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: [email protected]; line: 40, column: 21] 

「セキュリティ」で後述する「タグ」と呼ばれるXML属性のテキストですドキュメント。

私は次のように変更を試みましたが、例外は排除されましたが、POJOの緊急性のためにnull値が返されました。

public class Item { 
    @JacksonXmlProperty(localName = "urgency") 
    @JacksonXmlText 
    private String urgency; 
} 

私はここに明らかなものがありません。この要素のテキストを、Jacksonを使用してPOJOのStringフィールドに変換する最良の方法は何ですか?

私が扱っている完全なクラスとXMLドキュメントは次のとおりです。

XML:今

<rss version="2.0"> 
    <channel> 
     <title>Title</title> 
     <description>Description</description> 
     <copyright>Copyright info</copyright> 
     <ttl>5</ttl> 
     <pubDate>Thu, 27 Apr 2017 17:21:40 GMT</pubDate> 
     <item> 
      <title>Title of event in U.S.</title> 
      <description>Description here</description> 
      <fulldescription>Full description here</fulldescription> 
      <link>http://www.website.com</link> 
      <pubDate>Thu, 27 Apr 2017 17:13:48 GMT</pubDate> 
      <locations> 
       <location> 
        <name>New York, NY</name> 
        <latitude>40.714502</latitude> 
        <longitude>-74.006998</longitude> 
        <code>NYC</code> 
        <city>New York</city> 
        <state>New York</state> 
        <country>United States</country> 
        <region>North America</region> 
       </location> 
      </locations> 
      <source>AP</source> 
      <urgency id="UrgAttention">Attention</urgency> 
      <categories> 
       <category id="CatTransp">Transportation</category> 
      </categories> 
      <destinations> 
       <destination code="NYC" id="US" lat="40.714502" longitude="-74.006998">New York, New York</destination> 
      </destinations> 
      <designations /> 
      <related /> 
      <tags>Railway disruptions</tags> 
      <guid>3d64388fc639475dc9aeaabf81ee87bd</guid> 
     </item> 
    </channel> 
</rss> 

クラス。簡潔さのためゲッターとセッターが省略されています。 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; 
} 

アイテムクラス(JSONのプロパティはJSONへのマーシャリングの結果のためのものであるが、それらを削除すると、結果は変わりません):

public class Item { 
    @JacksonXmlProperty(localName = "title") 
    private String title; 

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

    @JacksonXmlProperty(localName = "fulldescription") 
    @JsonProperty("full_description") 
    private String fullDescription; 

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

    @JacksonXmlProperty(localName = "pubDate") 
    @JsonProperty("publish_date") 
    private String pubDate; 

    @JacksonXmlElementWrapper(localName = "locations") 
    @JacksonXmlProperty(localName = "location") 
    private List<Location> locations; 

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

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

    @JacksonXmlElementWrapper(localName = "categories") 
    @JacksonXmlProperty(localName = "category") 
    private List<Category> categories; 

    @JacksonXmlElementWrapper(localName = "destinations") 
    @JacksonXmlProperty(localName = "destination") 
    private List<Destination> destinations; 

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

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

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

    //getters and setters below here, no annotations 
} 

解析しようとするとエラーが発生する(名前空間省略):

"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: [email protected]; 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: [email protected]; 
line: 42, column: 32] (through reference chain: 
com.namespacestuff.FeedRoot[\"channel\"]- 
>com.namespacestuff.FeedChannel[\"item\"]->java.util.ArrayList[5])" 
+0

私は* @ JacksonXmlText *正しくないと思います。おそらく、POJOのすべてのプロパティを提供する必要があります。 –

+0

残りのxml要素を意味しますか?もしそうなら、私はすでにそれをやっています。 –

答えて

2

UPDATE

OPが私の答えの後に更新されたので、私はいくつかの考察を加えます。

提供されているコードでも、の項目要素だけをデシリアライズしようとすると、すべて正常です。

すべてのrss要素が含まれている場合に問題が発生します。

XMLを見ると、問題はのFeedChannelの定義にあります。私はアイテムに、この削除useWrapperローカル名を変更しようと

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

は、その後、私はそれに応じてXMLを変更しました。

<items><item>...</item></items> 

すべてが機能しました。

私は以下の書いたように、あなたは緊急プロパティの@JacksonXmlText注釈を必要としません。

それはuseWrapperがないだけで、あなたの現在のリストのための動作を変更しとしてジャクソン上のバグのように見えます。

urgencyプロパティアトリビュートidは、プロパティを配列に変換します。 属性を削除すると、すべて正常です。

これまでのところ、これはジャクソンのライブラリの問題だと思うので、あなたはそのケースを報告してください。


オリジナル答え

あなたは私が考えるポイントどこにエラーがないとしてあなたは、必要なすべてのコードを投稿する欠場。

私は作品例を作った:ここでは

は私のPOJOである:ここでは

@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); 
     } 

    } 
} 

エラーなし、何の問題は、それだけでは動作しません。

のJava 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> 
+0

好奇心。メインの投稿を編集して、完全なXML文書とすべての注釈を含めます。 –

+0

@MarkAbersoldあなたは私の答えの後にOPを更新しました。問題はない、私はそれを更新した。 –

+0

ありがとうございます。私はXMLを変更することができないので、これは回避しなければならないようなものです。 –

関連する問題