![](/img/trans.png)
[英]JAXB @XmlAdapter: Map -> List adapter? (marshall only)
[英]How can JAXB XmlAdapter be used to marshall lists?
此類的實例是大型對象圖的一部分,而不是對象圖的根:
public class Day
{
public Day(LocalDate date, List<LocalTime> times)
{
this.date = date;
this.times = times;
}
public Day()
{
this(null, null);
}
public LocalDate getDate()
{
return date;
}
public List<LocalTime> getTimes()
{
return times;
}
private final LocalDate date;
private final List<LocalTime> times;
}
使用Jersey和JAXB將對象圖轉換為JSON。 我XmlAdapter
的注冊為LocalDate
和LocalTime
。
問題在於它僅適用於date
屬性,而不適用於times
屬性。 我懷疑這與times
是一個列表而不是一個單一值有關。 然后,如何告訴Jersey / JAXB使用注冊的XmlAdapter
將times
列表中的每個元素編組?
更新:
我通過添加標量LocalTime
屬性並觀察JSON中的預期輸出,確認LocalTime
編組確實適用於標量LocalTime
屬性。
為了完整起見,這里是package-info.java:
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(value = LocalDateAdapter.class, type = LocalDate.class),
@XmlJavaTypeAdapter(value = LocalTimeAdapter.class, type = LocalTime.class)
})
package same.package.as.everything.else;
LocalDateAdapter
:
public class LocalDateAdapter extends XmlAdapter<String, LocalDate>
{
@Override
public LocalDate unmarshal(String v) throws Exception
{
return formatter.parseLocalDate(v);
}
@Override
public String marshal(LocalDate v) throws Exception
{
return formatter.print(v);
}
private final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyyMMdd");
}
LocalTimeAdapter
:
public class LocalTimeAdapter extends XmlAdapter<String, LocalTime>
{
@Override
public LocalTime unmarshal(String v) throws Exception
{
return formatter.parseLocalTime(v);
}
@Override
public String marshal(LocalTime v) throws Exception
{
return formatter.print(v);
}
private final DateTimeFormatter formatter = DateTimeFormat.forPattern("HHmm");
類的XmlAdapter
應用於該類型的映射字段/屬性,對於集合,則應用於集合中的每個項目。 下面的示例證明了這可行。 您是否嘗試過將示例獨立運行到XML以驗證這種方式的映射。 懷疑問題是XmlAdapter
以外的其他問題。
StringAdapter
以下XmlAdapter
將在解組操作時將String
轉換為小寫,並在編組時將其轉換為大寫。
package forum14569293;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class StringAdapter extends XmlAdapter<String, String> {
@Override
public String unmarshal(String v) throws Exception {
return v.toLowerCase();
}
@Override
public String marshal(String v) throws Exception {
return v.toUpperCase();
}
}
包信息
就像您的問題一樣,將使用包級別@XmlJavaTypeAdapters
批注來注冊XmlAdapter
。 這將為此包內所有映射的String
屬性注冊此XmlAdapter
(請參閱: http : XmlAdapter
)。
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
})
package forum14569293;
import javax.xml.bind.annotation.adapters.*;
根
下面是一個與您的Day
類相似的示例域模型,具有兩個映射的屬性。 第一個是String
類型,第二個是List<String>
。 關於Day
類,我注意到的一件事是您只有get
方法。 這意味着您將需要為JAXB impl添加一個@XmlElement
批注,以考慮該映射屬性。
package forum14569293;
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Root {
public Root(String foo, List<String> bar) {
this.foo = foo;
this.bar = bar;
}
public Root() {
this(null, null);
}
@XmlElement
public String getFoo() {
return foo;
}
@XmlElement
public List<String> getBar() {
return bar;
}
private final String foo;
private final List<String> bar;
}
演示
package forum14569293;
import java.util.*;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
List<String> bar = new ArrayList<String>(3);
bar.add("a");
bar.add("b");
bar.add("c");
Root root = new Root("Hello World", bar);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
產量
下面是運行演示代碼的輸出,我們看到XmlAdapter
將所有字符串都轉換為大寫。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<bar>A</bar>
<bar>B</bar>
<bar>C</bar>
<foo>HELLO WORLD</foo>
</root>
UPDATE
謝謝。 我嘗試了一下,XML只包含一個空標記,這意味着JAXB不喜歡POJO模型。 (也許它應該可序列化?)
JAXB不需要POJO實現Serializable
。
這很有趣,因為它似乎表明JAXB唯一起作用的部分是將其批注和其他一些接口(例如XmlAdapter)借給JSON(反)序列化器,並且關系就在那里結束了。
這取決於用作JSON綁定層的內容。 JAXB(JSR-222)規范不涵蓋JSON綁定,因此這種類型的支持超出了規范。 EclipseLink JAXB(MOXy)提供了本機JSON綁定(我是MOXy主管),您可以執行以下操作:
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
marshaller.marshal(root, System.out);
並獲得將XmlAdapter
考慮在內的以下輸出:
{
"bar" : [ "A", "B", "C" ],
"foo" : "HELLO WORLD"
}
但是,當我有機會的時候,我將盡我所能來使JAXB生成XML,這可能會揭示出其他東西。
這將很有用,因為我不認為您看到的是JAXB問題,而是您正在使用的JSON綁定層中的問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.