杰克逊坚持要映射一个未知的财产

时间:2018-09-19 19:10:45

标签: java xml jackson

全部, 我正在使用Jackson 2.9.5

我正在尝试解析Blazemeter Taurus的final-stats模块的XML输出。

有一个XML元素“ Group”,其子级为“ perc”,用于百分位数。 Perc具有未映射的“名称”子级。我认为应该忽略“姓名”子级,因为如果我删除@JsonIgnorePropertues(ignoreUnknown=true),杰克逊会因为无法识别“姓名”而大怒。

但是,在反序列化Group时,不会忽略名称。相反,我得到

  

com.fasterxml.jackson.databind.exc.MismatchedInputException:无法构造com.mycompany.myproject.Percentile的实例(尽管存在至少一个Creator):没有用于从字符串值反序列化的字符串参数构造函数/工厂方法('perc / 90.0')    在[来源:(BufferedInputStream);第4行,第20列](通过参考链:com.mycompany.myproject.Group [“ perc”]-> java.util.ArrayList [0])

“ perc / 90.0”是未映射的“名称”元素的值。

更奇怪的是,当我尝试仅反序列化perc元素时,它可以正常工作。

这是失败的XML:

<?xml version='1.0' encoding='UTF-8'?>
<Group label="https://myhost.mycompany.com:8443/login?from=%2F">
  <perc value="0.19300" param="90.0">
    <name>perc/90.0</name>
  </perc>
</Group

这是我的反序列化代码:

XmlMapper mapper = new XmlMapper();
mapper.registerModule(new JaxbAnnotationModule());
InputStream in =  Thread.currentThread().getContextClassLoader().getResourceAsStream("taurus/group-small.xml");
Group group = mapper.readValue(in, Group.class);

此XML有效:

<perc value="0.19300" param="90.0">
  <name>perc/90.0</name>
</perc>

使用反序列化代码:

XmlMapper mapper = new XmlMapper();
mapper.registerModule(new JaxbAnnotationModule());
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("taurus/percentile2.xml");
Percentile p = mapper.readValue(in, Percentile.class);

这些是我的映射类:

package com.mycompany.myproject;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement(name="perc")
public class Percentile {

    @XmlAttribute(name="value")
    private double value;

    @XmlAttribute(name="param")
    private double name;

    public double getValue() {
        return value;
    }

    public void setValue(double value) {
        this.value = value;
    }

    public double getName() {
        return name;
    }

    public void setName(double name) {
        this.name = name;
    }
}

package com.mycompany.myproject;

import java.util.List;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
@XmlRootElement(name="Group")
public class Group {

    @XmlAttribute(name="label")
    private String label;
    @XmlElement(name="perc")
    private List<Percentile> responseTimePercentiles;

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    public List<Percentile> getResponseTimePercentiles() {
        return responseTimePercentiles;
    }

    public void setResponseTimePercentiles(List<Percentile> responseTimePercentiles) {
        this.responseTimePercentiles = responseTimePercentiles;
    }
}

谢谢

2 个答案:

答案 0 :(得分:2)

这里的问题是,您的Group类定义了一个百分位数列表,这些百分位数映射到名为<perc>的xml列表元素。您的组xml不包含名为<perc>的xml列表元素,但在根xml的正下方具有<perc>元素。

由于@XmlElement(name="perc")应用于列表字段,并且@XmlRootElement(name="perc")应用于各个百分比xml元素,因此您的组映射期望的xml结构类似于: / p>

<group>
  <perc/>
      <perc/> 
      <perc/>
      <perc/> 
  <perc/> 
<group>

实际的XML结构是:

<group>
  <perc/> 
  <perc/>
  <perc/> 
<group>

要使其正常工作,您有2种选择:

  1. 更改XML,使其包含一个包含列表的元素(例如<percentiles>),并将列表字段上的注释更改为@XmlElement(name="percentiles")

  2. 容纳一个事实,即您没有一个表示映射中列表的xml元素。为此,您需要:

    添加以下方法到您的组映射器中:

    @JsonSetter(value = "perc")
    public void setPercentile(Percentile percetile) {
       this.responseTimePercentiles.add(percetile);
    }
    
    从组类的列表字段中

    删除。{p>

其最终结果是,映射不会期望在XML中找到包含列表的元素,并且每次遇到@XmlElement(name="perc")元素时,它只会将其添加到列表中。

答案 1 :(得分:0)

作为替代方法,替代语法可以起作用,例如,指定要忽略的内容:

@JsonIgnoreProperties({ "internalId", "secretKey" })