使用杰克逊没有字符串参数构造函数/工厂方法从字符串值反序列化的XML映射(“比利时华夫饼”)

时间:2019-06-12 18:04:53

标签: java xml jackson

出于学习目的,我试图将xml文件映射到pojo。我的xml看起来像这样:

<breakfast_menu>
   <food>
     <name>Belgian Waffles</name>
     <price>$5.95</price>
     <description>
        Two of our famous Belgian Waffles with plenty of real maple syrup
     </description>
     <calories>650</calories>
   </food>
   <food>
     <name>Strawberry Belgian Waffles</name>
     <price>$7.95</price>
     <description>
        Light Belgian waffles covered with strawberries and whipped cream
     </description>
     <calories>900</calories>
   </food>
</breakfast_menu>

Breakfes实体类

@JacksonXmlRootElement(localName = "breakfast_menu")
public class BreakfestFood {

    private List<Food> food;

    public BreakfestFood() {}

    public List<Food> getFood() {
        return food;
    }

    public void setFood(List<Food> food) {
        this.food = food;
    }

}

食物实体类

@JacksonXmlRootElement(localName = "food")
public class Food {

    @JacksonXmlProperty(localName = "name")
    private String name;
    @JacksonXmlProperty
    private double price;
    @JacksonXmlProperty
    private String description;
    @JacksonXmlProperty
    private int calories;

主要功能:

public static void main(String[] args) {
    File file = new File("X:\\food.xml");
    XmlMapper xmlMapper = new XmlMapper();

    try {
        String xml = inputStreamToString(new FileInputStream(file));
        BreakfestFood value = xmlMapper.readValue(xml, BreakfestFood.class);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

当我运行这段代码时,我将得到如下堆栈: 从字符串值反序列化的字符串参数构造函数/工厂方法(“比利时华夫饼”)。因此,它似乎无法映射食物的名称值。有人知道哪里出了问题吗?

1 个答案:

答案 0 :(得分:1)

您的映射不正确。 要检查出什么问题,建议您序列化一个简单的对象。

BreakfestFood bf = new BreakfestFood();
Food f1 = new Food();
f1.setName("f1Name");
f1.setCalories(20);
f1.setDescription("desc");
f1.setPrice(11.1);
bf.setFood(List.of(f1));

System.out.println(xmlMapper.writeValueAsString(bf));

Output: 
<breakfast_menu>
  <food>
    <food>
      <price>11.1</price>
      <description>desc</description>
      <calories>20</calories>
      <name>f1Name</name>
    </food>
  </food>
</breakfast_menu>

如您所见,您将获得该列表的额外包装。 要摆脱它,请使用:

@JacksonXmlRootElement(localName = "breakfast_menu")
public class BreakfestFood {

    // Use this to change element name:
    // @JacksonXmlProperty(localName = "food")
    @JacksonXmlElementWrapper(useWrapping = false)
    private List<Food> food;

    // getters and setters
}

最重要的是:

    如果您有公众参与者,
  • 食品中的注释是多余的
  • 价格标签中的值不是双精度。您需要调整映射以解析货币值。自定义@JsonSerialize@JsonDeserialize是解决此问题的一种方法。
  • 通常来说,将价格翻倍是一个糟糕的主意。