JAXB包装器+适配器忽略输出

时间:2018-06-21 04:51:10

标签: java xml jaxb unmarshalling

所以我有一个奇怪的问题。我包装了一个XML元素,需要对该元素进行解析,然后将其转换为其他类型。

我发现如果使用@XmlElement(type = PlaceHolder.class),我可以让JAXB将所有必需的信息解析到PlaceHolder中,然后使用@XmlJavaTypeAdapter将PlaceHolder转换为所需的类。

这是System.out的输出

||tree.log, 1  tree.log
tree.log x 1/2
||test.oo, 2  null
||craft.lumber, 2  null
wb.lumber Lumber 10.0 | 0 -> 0

这让我相信

  1. 将xml解析为PlaceHolder类(XMLItemStack)
  2. 适配器确实尝试转换PlaceHolder类
  3. 适配器的输出将被忽略。

XML

<recipe id="wb.lumber">
    <name>Lumber</name>
    <time>10</time>
    <building>workbench</building>
    <in>
        <item id="tree.log">
            <stack>1</stack>
        </item>
        <item id="test.oo">
            <stack>2</stack>
        </item>
    </in>
    <out>
        <item id="craft.lumber">
            <stack>2</stack>
        </item>
    </out>
</recipe>

MainClass

@XmlRootElement
public class Recipe {
    @XmlAttribute
    @XmlID
    String id;
    @XmlElement
    String name;
    @XmlElement
    float time;

    @XmlElementWrapper(name="in")
    @XmlElement(name="item",type=XMLItemStack.class)
    @XmlJavaTypeAdapter(xmlToItemStackAdapter.class)
    ItemStack[] req;
    @XmlElementWrapper(name="out")
    @XmlElement(name="item",type=XMLItemStack.class)
    @XmlJavaTypeAdapter(xmlToItemStackAdapter.class)
    ItemStack[] res;

    @Override
    public String toString(){
        String str = id+" "+name+" "+time+" | "+(req == null ? 0 : req.length)+" -> "+(res == null ? 0 : res.length);
        return str;
    }
}

适配器和占位符类

@XmlRootElement(name="item")
static class XMLItemStack {
    @XmlAttribute
    @XmlID
    String id;
    @XmlElement
    int stack;

    @Override
    public String toString(){
        return id+" "+stack;
    }

    public XMLItemStack(){}

    public XMLItemStack(String name,int size){
        id = name;
        stack = size;
    }
}

static class xmlToItemStackAdapter extends XmlAdapter<XMLItemStack,ItemStack> {

    @Override
    public XMLItemStack marshal(ItemStack v) throws Exception {
        return new XMLItemStack(v.getItem().getID(),v.getCount());
    }

    @Override
    public ItemStack unmarshal(XMLItemStack v) throws Exception {
        Item it = Items.getItem(v.id);
        System.out.println("||"+v.id+", "+v.stack+"  "+it);

        if(it == null){
            throw new Exception("Unable to Find Item for Crafting Recipe");
        }

        System.out.println(new ItemStack(it,v.stack));

        return new ItemStack(it,v.stack);
    }
}

1 个答案:

答案 0 :(得分:0)

超级困惑。

无论是否指定@XmlElement类型,并将ItemStack []更改为数组列表即可解决此问题。

@XmlRootElement
public class Recipe {
    @XmlAttribute
    @XmlID
    String id;
    @XmlElement
    String name;
    @XmlElement
    float time;

    @XmlElementWrapper(name="in")
    @XmlJavaTypeAdapter(xmlToItemStackAdapter.class)
    @XmlElement(name="item",type=XMLItemStack.class)
    ArrayList<ItemStack> req;
    @XmlElementWrapper(name="out")
    @XmlJavaTypeAdapter(xmlToItemStackAdapter.class)
    @XmlElement(name="item")
    ArrayList<ItemStack> res;

    @Override
    public String toString(){
        String str = id+" "+name+" "+time+" | "+(req == null ? 0 : req.size())+" -> "+(res == null ? 0 : res.size());
        return str;
    }
}