此类的实例是大对象图的一部分,不在对象图的根部:
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使用注册的times
编组XmlAdapter
列表中的每个元素?
更新
通过添加标量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");
答案 0 :(得分:4)
类的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
。这将为此包中的所有映射XmlAdapter
属性注册此String
(请参阅:http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html)。
@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>
<强>更新强>
感谢。我试了一下,XML只包含一个空标签, 这意味着JAXB不喜欢POJO模型。 (也许它应该是Serializable?)
JAXB不要求POJO实现Serializable
。
这很有趣,因为它似乎表明唯一的一部分 JAXB在这方面的作用是借给它的注释和其他一些 接口(例如XmlAdapter)到JSON(de)序列化器,那就是 关系结束的地方。
这取决于用作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绑定层中的问题。