【问题标题】:Jaxb unmarshall returning nullJaxb 解组返回 null
【发布时间】:2019-10-07 09:15:33
【问题描述】:

我正在尝试通过 jaxb 解组 xml 文件。

我的 xml 文件是:

<root id="1">
   <fields>
      <field id="2">
         <values>
            <value><some></value>
         </values>
      </field>
      <field id="3">
         <values>
            <value><xxx></value>
         </values>
      </field>
     <field id="483">
         <values />
      </field>
     </fields>
</root>

***重要 键值的内容可以是任意类型(字符串、日期、整数)。

我解组元素的代码:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Fields", propOrder = {
    "cuestionarios"
})
@XmlRootElement(name = "root")
public class Fields {
    @XmlElement(name = "fields", required = true)
    protected Field cuestionarios;

    public Field getCuestionarios() {
        return cuestionarios;
    }

    public void setCuestionarios(Field cuestionarios) {
        this.cuestionarios = cuestionarios;
    }
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Field", propOrder = {
    "values"
})
public class Field {
    @XmlElement(name = "field", required = true)
    protected List<Value> values;

    public List<Value> getValues() {
        if (values == null) {
        values = new ArrayList<>();
    }
    return this.values;
    }
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Value", propOrder = {
    "value"
})
public class Value {
    @XmlElement(name = "values", required = true)
    protected List<Object> value;

    public Value(){

    }

    public List<Object> getValue() {
        if (value == null) {
        value = new ArrayList<>();
    }
    return this.value;
    }

    public void setValue(List<Object> value) {
        this.value = value;
    }

我在 cuestionarios 中得到空值。我不确定这是否是 xml 中的错误,格式错误,或者我在 xml 标签中有一些错误。我认为错误出现在 xml 的标签中。 列表已填满,但其所有字段均为空。

谢谢。

【问题讨论】:

    标签: java xml jaxb unmarshalling


    【解决方案1】:

    做你想做的事(我能想到的)的方式如下。

    创建一个如下所示的类:

    @XmlAccessorType(XmlAccessType.FIELD)
    public class ValueContent {
    
        @XmlElement(name = "value")
        private String content;
    }
    

    并调整您的 Value 类以使用它而不是 Object,如下所示:

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "Value", propOrder = {
            "value"
    })
    public class Value {
        @XmlElement(name = "values", required = true)
        protected List<ValueContent> value;
    
        public Value(){
    
        }
    
        public List<ValueContent> getValue() {
            if (value == null) {
                value = new ArrayList<>();
            }
            return this.value;
        }
    
        public void setValue(List<ValueContent> value) {
            this.value = value;
        }
    }
    

    编辑以回复评论:

    在这种情况下,你可以这样做:

    @XmlAccessorType(XmlAccessType.FIELD)
    public class ValueContent {
    
        @XmlElements({
                @XmlElement(name = "text", type = String.class),
                @XmlElement(name = "number", type = Integer.class)
        })
        private Object content;
    }
    

    但是你的 xml 将不得不根据类型使用不同的标签,如下所示:

    <root id="1">
        <fields>
            <field id="2">
                <values>
                    <number>1</number>
                </values>
            </field>
            <field id="3">
                <values>
                    <text>value1</text>
                </values>
            </field>
        </fields>
    </root>
    

    它必须这样做,否则将无法知道将其解组到哪个类。

    另一种选择(半生不熟的想法)是为该字段使用适配器并尝试在那里获取输入的类型并正确转换。

    编辑 2 以显示适配器的使用: 您可以按如下方式创建适配器:

    public class CastingAdapter extends XmlAdapter<String, Object> {
    
        private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    
        @Override
        public String marshal(Object arg0) throws Exception {
            return null;
        }
    
        @Override
        public Object unmarshal(String arg0) throws Exception {
            if(StringUtils.isNumeric(arg0)) {
                return Integer.valueOf(arg0);
            }
    
            if(StringUtils.isAlphanumeric(arg0)) {
                return arg0;
            }
    
            if(isValidDate(arg0)) {
                return dateFormat.parse(arg0);
            }
    
            return arg0;
        }
    
        private boolean isValidDate(String inDate) {
    
            dateFormat.setLenient(false);
            try {
                dateFormat.parse(inDate.trim());
            } catch (ParseException pe) {
                return false;
            }
            return true;
        }
    }
    

    并在 ValueContent 中使用此适配器:

    @XmlAccessorType(XmlAccessType.FIELD)
    public class ValueContent {
    
        @XmlJavaTypeAdapter(CastingAdapter.class)
        private Object value;
    }
    

    对于如下的xml:

    <root id="1">
        <fields>
            <field id="1">
                <values>
                    <value>2009-12-31</value>
                </values>
            </field>
            <field id="2">
                <values>
                    <value>1</value>
                </values>
            </field>
            <field id="3">
                <values>
                    <value>value1</value>
                </values>
            </field>
        </fields>
    </root>
    

    它会做的工作。

    【讨论】:

    • 该解决方案对我无效,因为我的 xml 的值可以是任何类型(字符串、日期、int),因此对象
    • 无法更改xml代码。有没有适合规格的解决方案?
    • @Diego 有一个解决方案,我在回复中添加了它。检查它是否符合您的喜好。
    • 它可以工作,但是当找到以下字段时,jaxb 处理会停止: 我已经尝试过 required = false ,但它一直停止。
    • @Diego 停止是什么意思?我试过你的例子,效果很好
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多