gpt4 book ai didi

java - JAXB/Moxy 将 XmlElements 与 XmlAdapter 结合使用

转载 作者:行者123 更新时间:2023-11-30 11:27:35 25 4
gpt4 key购买 nike

我试着完全按照这个 question 中描述的去做与 MOXY。但是我有一些不同的行为,但结果是一样的。它不起作用。

我使用@XmlElements 并为每个具体类添加了一个带有名称和类型的@XmlElement。对于没有适配器的所有类,它都能完美运行,但不适用于带有 PolyAdapter 的类。

在我的例子中,将调用适配器来编码对象。但它只写入 xml 文件中的一个条目。

<?xml version="1.0" encoding="UTF-8"?>
<fooContainer>
<poly PolyName="PolyN$1">ABCBCD</poly>
<cPlexPoly>moxy.CPlexPoly$CPlexPolyAdapter$CCPWrapper@480bdb19</cPlexPoly>
</fooContainer>

解码器根本不会被调用。

我在两种情况下测试了 MOXy 2.5.0 和当前的 RC3 2.5.1,结果相同。我还启用了调试输出,没有警告或错误。

或者也许还有另一种方法可以让它工作

更新1:提供模型

我创建了一个小示例来展示我的 MOXy 2.5.0 问题

接口(interface):

@XmlRootElement
public interface Foo {
public List<String> getCoordinates();
}

没有 XmlAdapter 的类:

@XmlRootElement(name="poly")
public class Poly implements Foo {
@XmlAttribute
String PolyName = "PolyN$1";

@XmlAnyElement
private List<String> coordinates = new LinkedList<>();

@Override
public List<String> getCoordinates() {
return coordinates;
}

public void addCoordinate( final String poly ) {
coordinates.add( poly );
}
}

使用 XmlAdapter 类:

@XmlJavaTypeAdapter(CPlexPolyAdapter.class)
public class CPlexPoly implements Foo {
private Map<String, String> values = new HashMap<>();

@Override
public List<String> getCoordinates() {
return new ArrayList<>(values.values());
}

public void addCoordinate( final String poly ) {
values.put( Integer.toString( poly.hashCode()), poly );
}

public List<String> getKeys() {
return new ArrayList<>(values.keySet());
}


public static class CPlexPolyAdapter extends XmlAdapter<CCPWrapper, CPlexPoly> {

@XmlRootElement(name="wrapper")
public static class CCPWrapper {
@XmlAnyElement
List<String> keys = new ArrayList<>();
@XmlAnyElement
List<String> values = new ArrayList<>();
}

@Override
public CPlexPoly unmarshal(CCPWrapper v) throws Exception {
// Won't be called.
return null;
}

@Override
public CCPWrapper marshal(CPlexPoly v) throws Exception {
if( v == null ) {
return null;
}

CCPWrapper wrapper = new CCPWrapper();
wrapper.values.addAll( v.getCoordinates() );
wrapper.keys.addAll( v.getKeys() );

return wrapper;
}
}
}

简单容器类:

@XmlRootElement(name="fooContainer") 
public class FooContainer {

@XmlElements({
@XmlElement(name = "poly", type = Poly.class),
@XmlElement(name = "cPlexPoly", type = CPlexPoly.class)
})
public List<Foo> container = new LinkedList<>();
}

主要内容:

public class Main {
public static void main(String[] args) {
FooContainer fc = new FooContainer();

Poly poly = new Poly();
poly.addCoordinate("ABC");
poly.addCoordinate("BCD");

CPlexPoly cpoly = new CPlexPoly();
cpoly.addCoordinate("XYZ");
cpoly.addCoordinate("WXY");

fc.container.add( poly );
fc.container.add( cpoly );

/* Marshall */
JAXBContext context;
try {
context = JAXBContext.newInstance( FooContainer.class );
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal( fc, new FileWriter("fc.xml") );
}
catch (JAXBException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

/* UnMarshall */
}
}

我还更新了上面描述的结果。谢谢。

更新 2:简化包装

即使这个简单的包装器只包含一个属性,也没有任何改变。

@XmlJavaTypeAdapter(CPlexPolyAdapter.class)
public class CPlexPoly implements Foo {

private Map<String, String> values = new HashMap<>();

@Override
public List<String> getCoordinates() {
return new ArrayList<>(values.values());
}

public void addCoordinate( final String poly ) {
values.put( Integer.toString( poly.hashCode()), poly );
}

public List<String> getKeys() {
return new ArrayList<>(values.keySet());
}


public static class CPlexPolyAdapter extends XmlAdapter<CCPWrapper, CPlexPoly> {

@XmlRootElement(name="wrapper")
public static class CCPWrapper {

@XmlAttribute
String test = "test";
}

@Override
public CPlexPoly unmarshal(CCPWrapper v) throws Exception {
// Won't be called.
return null;
}

@Override
public CCPWrapper marshal(CPlexPoly v) throws Exception {
if( v == null ) {
return null;
}

CCPWrapper wrapper = new CCPWrapper();
return wrapper;
}
}
}

因此,如果有人知道哪里出了问题,那将非常有帮助。谢谢基督徒

最佳答案

注意:我是 EclipseLink JAXB (MOXy) JAXB (JSR-222) 的领导和成员专家组。

您遇到的问题是由于 CCPWrapper 类映射不正确造成的。不允许使用 @XmlAnyElement 映射两个字段/属性。

    @XmlRootElement(name = "wrapper")
public static class CCPWrapper {
@XmlAnyElement
List<String> keys = new ArrayList<>();
@XmlAnyElement
List<String> values = new ArrayList<>();
}

当我修改您的代码以删除其中一个 @XmlAnyElement 注释时,一切似乎都正常工作。


更新#1

Thank you for your answer. But no I still get the same output. I even removed both lists with the XmlAnyElement annotation and just added a simple XmlAttribute. The output doesn't change. See the updated Wrapper class in question.

我刚刚注意到,当我尝试您的代码时,我已将类型为 CPlexPoly 的字段添加到 FooContainer 类中。除了我之前的建议之外,这还导致 XmlAdapter 应用于 container 字段。

import java.util.*;
import javax.xml.bind.annotation.*;

@XmlRootElement(name = "fooContainer")
public class FooContainer {

@XmlElement
private final CPlexPoly workaround = null;

@XmlElements({
@XmlElement(name = "poly", type = Poly.class),
@XmlElement(name = "cPlexPoly", type = CPlexPoly.class)
})
public List<Foo> container = new LinkedList<>();

}

您可以采取类似的解决方法。我已经打开了以下错误,您可以使用它来跟踪我们在实际修复中的进度:


更新#2

更好的解决方法是在用于创建 JAXBContext 的类中包含 CCPWrapper 类,如下所示:

    context = JAXBContext.newInstance( FooContainer.class, CCPWrapper.class );

关于java - JAXB/Moxy 将 XmlElements 与 XmlAdapter 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19266097/

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