【问题标题】:Jackson insists on mapping an unknown property杰克逊坚持绘制未知属性
【发布时间】:2019-02-24 00:50:43
【问题描述】:

所有, 我正在使用杰克逊 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 的实例(尽管至少存在一个创建者):没有从字符串值反序列化的字符串参数构造函数/工厂方法('perc/90.0' ) 在 [来源:(BufferedInputStream);行:4,列:20](通过引用链:com.mycompany.myproject.Group["perc"]->java.util.ArrayList[0])

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

更奇怪的是,当我尝试仅反序列化 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;
    }
}

谢谢

【问题讨论】:

    标签: java xml jackson


    【解决方案1】:

    这里的问题是您的 Group 类定义了一个百分位列表,该列表映射到名为 &lt;perc&gt; 的 xml 列表元素。您的 Group xml 不包含名为 &lt;perc&gt; 的 xml 列表元素,但在根 xml 的正下方有 &lt;perc&gt; 元素。

    因为@XmlElement(name="perc") 应用于列表字段,而@XmlRootElement(name="perc")应用于各个百分位 xml 元素,所以您的组映射需要类似于以下内容的 xml 结构:

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

    实际的XML结构是:

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

    要使其正常工作,您有 2 个选项:

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

    2. 适应您没有表示映射中列表的 xml 元素这一事实。为此,您需要:

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

      @JsonSetter(value = "perc")
      public void setPercentile(Percentile percetile) {
         this.responseTimePercentiles.add(percetile);
      }
      

      从 Group 类的列表字段中删除 @XmlElement(name="perc") 注释。

    这样做的最终结果是映射不期望在 XML 中找到包含列表元素,并且每次遇到 &lt;perc&gt; 元素时,它只是将其添加到列表中。

    【讨论】:

      【解决方案2】:

      作为一种解决方法,替代语法是否有效,指定要忽略的内容,例如:

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

      【讨论】:

      • 谢谢,但在这种情况下我仍然遇到同样的错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-03
      • 2013-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-30
      • 2015-05-23
      相关资源
      最近更新 更多