Dis*_*tum 2 java json jaxb jersey xmladapter
此类的实例是大型对象图的一部分,并且不在对象图的根部:
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;
}
Run Code Online (Sandbox Code Playgroud)
使用 Jersey 和 JAXB 将对象图转换为 JSON。我已经XmlAdapter注册了LocalDate和LocalTime。
问题是它只对date财产有效,而不是对times财产有效。我怀疑这与列表times而不是单个值有关。那么,我如何告诉 Jersey/JAXBtimes使用注册的来编组列表中的每个元素XmlAdapter?
更新:
通过添加标量属性并观察 JSON 中的预期输出,我确认LocalTime编组确实适用于标量属性。LocalTimeLocalTime
为了完整起见,这里是 package-info.java:
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(value = LocalDateAdapter.class, type = LocalDate.class),
@XmlJavaTypeAdapter(value = LocalTimeAdapter.class, type = LocalTime.class)
})
package same.package.as.everything.else;
Run Code Online (Sandbox Code Playgroud)
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");
}
Run Code Online (Sandbox Code Playgroud)
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");
Run Code Online (Sandbox Code Playgroud)
类的forXmlAdapter应用于该类型的映射字段/属性,对于集合,应用于集合中的每个项目。下面的例子证明这是可行的。您是否尝试过独立运行 XML 示例来验证映射。怀疑问题是除XmlAdapter具体问题之外的其他问题。
字符串适配器
以下XmlAdapter将在解组操作中将 a 转换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();
}
}
Run Code Online (Sandbox Code Playgroud)
包信息
正如您的问题一样,@XmlJavaTypeAdapters将使用包级别注释来注册XmlAdapter. 这将为该包中的XmlAdapter所有映射属性注册此属性(请参阅:http: //blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html)。String
@XmlJavaTypeAdapters({
@XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
})
package forum14569293;
import javax.xml.bind.annotation.adapters.*;
Run Code Online (Sandbox Code Playgroud)
根
下面是一个示例域模型,与您的Day类类似,具有两个映射属性。第一个是 type String,第二个是List<String>。我注意到你的班级的一件事Day是你只有get方法。这意味着您需要@XmlElement为 JAXB impl 添加注释才能将其视为映射属性。
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;
}
Run Code Online (Sandbox Code Playgroud)
演示
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);
}
}
Run Code Online (Sandbox Code Playgroud)
输出
下面是运行演示代码的输出,我们看到所有字符串都被XmlAdapter.
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();
}
}
Run Code Online (Sandbox Code Playgroud)
更新
谢谢。我尝试了一下,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);
Run Code Online (Sandbox Code Playgroud)
并得到以下考虑XmlAdapter在内的输出:
{
"bar" : [ "A", "B", "C" ],
"foo" : "HELLO WORLD"
}
Run Code Online (Sandbox Code Playgroud)
尽管如此,当我有机会时,我会尽我所能让 JAXB 生成 XML,这可能会揭示其他内容。
这将很有用,因为我不相信您看到的是 JAXB 问题,而是您正在使用的 JSON 绑定层中的问题。
| 归档时间: |
|
| 查看次数: |
31920 次 |
| 最近记录: |