gpt4 book ai didi

java - JAXB XmlAdapter 如何用于编码列表?

转载 作者:行者123 更新时间:2023-11-30 07:19:36 26 4
gpt4 key购买 nike

此类的实例是大型对象图的一部分,不在对象图的根部:

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。我为 LocalDateLocalTime 注册了 XmlAdapter

问题是它只对 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;

本地日期适配器:

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

本地时间适配器:

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 以外的其他问题。

字符串适配器

以下 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>

更新

Thanks. I tried it and the XML consisted of one empty tag only, meaning there's something about the POJO model that JAXB doesn't like. (Perhaps it should be Serializable?)

JAXB 不要求 POJO 实现 Serializable

That's interesting because it seems to indicate that the only part JAXB plays in this is to lend its annotations and some other interfaces (e.g. XmlAdapter) to the JSON (de)serializer and that's where the relationship ends.

这取决于什么被用作 JSON 绑定(bind)层。 JAXB (JSR-222) 规范不包括 JSON 绑定(bind),因此这种类型的支持超出了规范。 EclipseLink JAXB (MOXy) 提供 native JSON 绑定(bind)(我是 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"
}

Nevertheless, when I get an opportunity I will do what I can to get JAXB to generate the XML and that may reveal something else.

这会很有用,因为我不相信您看到的是 JAXB 问题,而是您正在使用的 JSON 绑定(bind)层中的问题。

关于java - JAXB XmlAdapter 如何用于编码列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14569293/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com