简体   繁体   English

JAXB XmlAdapter如何用于编组列表?

[英]How can JAXB XmlAdapter be used to marshall lists?

Instances of this class are part of a large object graph and are not at the root of the object graph: 此类的实例是大型对象图的一部分,而不是对象图的根:

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

The object graph is converted to JSON using Jersey and JAXB. 使用Jersey和JAXB将对象图转换为JSON。 I have XmlAdapter s registered for LocalDate and LocalTime . XmlAdapter的注册为LocalDateLocalTime

The problem is that it's only working for the date property and not the times property. 问题在于它仅适用于date属性,而不适用于times属性。 I suspect this has something to do with the fact that times is a list rather than a single value. 我怀疑这与times是一个列表而不是一个单一值有关。 How, then, do I tell Jersey/JAXB to marshall each element in the times list using the registered XmlAdapter ? 然后,如何告诉Jersey / JAXB使用注册的XmlAdaptertimes列表中的每个元素编组?

Update: 更新:

I confirmed that LocalTime marshalling is indeed working for scalar LocalTime properties by adding a scalar LocalTime property and observing the expected output in the JSON. 我通过添加标量LocalTime属性并观察JSON中的预期输出,确认LocalTime编组确实适用于标量LocalTime属性。

For completeness, here's package-info.java: 为了完整起见,这里是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 : 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 : 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");

An XmlAdapter for a class is applied to a mapped field/property of that type, and in the case of collections, for each item in the collection. 类的XmlAdapter应用于该类型的映射字段/属性,对于集合,则应用于集合中的每个项目。 The example below proves that this works. 下面的示例证明了这可行。 Have you tried running your example standalone to XML to verify the mappings that way. 您是否尝试过将示例独立运行到XML以验证这种方式的映射。 Is suspect the problem is something else other than the XmlAdapter specifically. 怀疑问题是XmlAdapter以外的其他问题。

StringAdapter StringAdapter

The following XmlAdapter will convert a String to lower case on the unmarshal operation and convert it to upper case when marshalled. 以下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();
    }

}

package-info 包信息

Just as in your question a package level @XmlJavaTypeAdapters annotation will be used to register the XmlAdapter . 就像您的问题一样,将使用包级别@XmlJavaTypeAdapters批注来注册XmlAdapter This will register this XmlAdapter for all mapped String properties within this package (see: http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html ). 这将为此包内所有映射的String属性注册此XmlAdapter (请参阅: http : XmlAdapter )。

@XmlJavaTypeAdapters({
    @XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
})
package forum14569293;

import javax.xml.bind.annotation.adapters.*;

Root

Below is a sample domain model similar to your Day class with two mapped properties. 下面是一个与您的Day类相似的示例域模型,具有两个映射的属性。 The first is of type String and the second List<String> . 第一个是String类型,第二个是List<String> One thing I notice about your Day class is that you only have get methods. 关于Day类,我注意到的一件事是您只有get方法。 This means that you will need to add an @XmlElement annotation for a JAXB impl to consider that a mapped property. 这意味着您将需要为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;

}

Demo 演示

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

    }

}

Output 产量

Below is the output from running the demo code we see that all the strings were converted to upper case by the XmlAdapter . 下面是运行演示代码的输出,我们看到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 UPDATE

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. 我尝试了一下,XML只包含一个空标记,这意味着JAXB不喜欢POJO模型。 (Perhaps it should be Serializable?) (也许它应该可序列化?)

JAXB does not require that POJOs implement 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 (eg XmlAdapter) to the JSON (de)serializer and that's where the relationship ends. 这很有趣,因为它似乎表明JAXB唯一起作用的部分是将其批注和其他一些接口(例如XmlAdapter)借给JSON(反)序列化器,并且关系就在那里结束了。

It depends on what is being used as the JSON binding layer. 这取决于用作JSON绑定层的内容。 The JAXB (JSR-222) specification does not cover JSON-binding so this type of support is beyond the spec. JAXB(JSR-222)规范不涵盖JSON绑定,因此这种类型的支持超出了规范。 EclipseLink JAXB (MOXy) offers native JSON-binding (I'm the MOXy lead) with it you could do something like: 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);

And get the following output that takes the XmlAdapter into account: 并获得将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生成XML,这可能会揭示出其他东西。

This would be useful as I do not believe what you are seeing is a JAXB issue, but an issue in the JSON binding layer that you are using. 这将很有用,因为我不认为您看到的是JAXB问题,而是您正在使用的JSON绑定层中的问题。

如何编组 ArrayList<object> [] 在 JAXB 中?<div id="text_translate"><p> 我有一个 ArrayList[] 类型的变量(列表),我想将它保存在 XML 中。 我尝试了 JAXB,但它只保存了“”字符串(“的重复”等于 list.length)并且在 ArrayLists 中没有任何项目。如果我尝试二维数组,它工作正常。如果我尝试 ArrayList,它也可以正常工作。我怎么解决这个问题?</p><p> 我的代码类似于:</p><pre> @XmlRootElement public class SomeClass { @XmlElement(name="part") private final ArrayList&lt;Object&gt;[] list; ... constructor, which fills the list variable }</pre><p> 有人可以告诉我该怎么做吗? 请。<br><br></p></div></object> - How to marshall ArrayList<Object>[] in JAXB?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 JAXB @XmlAdapter:Map - &gt; List adapter? (仅限马歇尔) - JAXB @XmlAdapter: Map -> List adapter? (marshall only) 如何直接调用JAXB XMLAdapter - How to invoke JAXB XMLAdapter directly 如何用jaxb编组? - How to marshall a set with jaxb? 如何在JAXB中将XML与名称空间编组? - How to marshall XML with namespace in JAXB? 如何编组 ArrayList<object> [] 在 JAXB 中?<div id="text_translate"><p> 我有一个 ArrayList[] 类型的变量(列表),我想将它保存在 XML 中。 我尝试了 JAXB,但它只保存了“”字符串(“的重复”等于 list.length)并且在 ArrayLists 中没有任何项目。如果我尝试二维数组,它工作正常。如果我尝试 ArrayList,它也可以正常工作。我怎么解决这个问题?</p><p> 我的代码类似于:</p><pre> @XmlRootElement public class SomeClass { @XmlElement(name="part") private final ArrayList&lt;Object&gt;[] list; ... constructor, which fills the list variable }</pre><p> 有人可以告诉我该怎么做吗? 请。<br><br></p></div></object> - How to marshall ArrayList<Object>[] in JAXB? 如何在JAXB中编组一个未包装的集合? - How to marshall an unwrapped collection in JAXB? JAXB with XmlAdapter for List to Map。 不按预期编组,但输出对象详细信息 - JAXB with XmlAdapter for List to Map. Does not marshall as expected but outputs object details 如何在JAXB XmlAdapter中使用通用对象列表 - How to use generic object List in JAXB XmlAdapter JAXB XMLAdapter:有没有办法将此方法转换为 JAXB XmlAdapter - JAXB XMLAdapter: Is there a way to convert this method into JAXB XmlAdapter JaxB如何将列表的内容编组为单独的标签 - JaxB How to marshall the content of a list as individual tags
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM