当使用Jackson的@JsonTypeInfo进行反序列化时,如何保留类型属性?

8

我的设置如下:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "dishName", defaultImpl = Food.class)
@JsonSubTypes(value = {
    @Type(name = "fries", value = Fries.class),
    @Type(name = "burger", value = Burger.class)
})
public class Food {
  private String dishName;

  @Override
  public String toString() {
    return dishName + ", type: " + this.getClass().getName();
  }
}

public class Fries extends Food { /*...*/ }

public class Burger extends Food { /*...*/ }

public class TryItOut {

  private static String foodString = "[ { \"dishName\":\"burger\" }, { \"dishName\":\"fries\" }, { \"dishName\":\"cabbage\" } ]";

  public static void main(String[] args) {
    ObjectMapper m = new ObjectMapper();
    try {
        Food[] food = m.readValue(foodString, Food[].class);
        for (Food dish : food) {
            System.out.println(dish);
        }
    } catch (IOException e) {
        System.out.println("something went wrong");
        e.printStackTrace();
    }
  }
}

我希望使用此方法对不能控制其内容的json进行反序列化(因此无法添加“正确”的类型信息)。我的问题是,显然dishName json属性用于确定子类型,但它没有反序列化到java字段中。是否有办法也实现这一点?换句话说:主方法打印

null, type: Burger
null, type: Fries
null, type: Food

在控制台上输出,但我想要它打印出来。
burger, type: Burger
fries, type: Fries
cabbage, type: Food

这非常讨厌,因为我以后无法找出最后一个对象是卷心菜。这使默认实现的好处失效。

编辑:

@Evil Raat的答案解决了问题。为了完整起见:Food类中的dishName字段需要使用@JsonProperty注释才能使此示例正常工作。因此,工作示例如下:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "dishName", defaultImpl = Food.class, visible = true)
@JsonSubTypes(value = {
    @Type(name = "fries", value = Fries.class),
    @Type(name = "burger", value = Burger.class)
})
public class Food {

  @JsonProperty
  private String dishName;

  @Override
  public String toString() {
    return dishName + ", type: " + this.getClass().getName();
  }
}

public class Fries extends Food { /*...*/ }

public class Burger extends Food { /*...*/ }

public class TryItOut {

  private static String foodString = "[ { \"dishName\":\"burger\" }, { \"dishName\":\"fries\" }, { \"dishName\":\"cabbage\" } ]";

  public static void main(String[] args) {
    ObjectMapper m = new ObjectMapper();
    try {
        Food[] food = m.readValue(foodString, Food[].class);
        for (Food dish : food) {
            System.out.println(dish);
        }
    } catch (IOException e) {
        System.out.println("something went wrong");
        e.printStackTrace();
    }
  }
}
2个回答

11
为了保持你在反序列化中使用的属性的价值,你只需要在@JsonSubTypes注解上将visible属性设置为true即可: @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "dishName", defaultImpl = Food.class, visible = true)

1

以上提供的修复方法对我来说并不起作用,因为初始序列化会产生一个空的重复字段。

var str = objectMapper.writeValueAsString(foodDto);
// { \"dishName\":\"burger\", ..., \"dishName\":null }

所以你需要像这样注释字段。
@JsonProperty(value = "dishName", access = JsonProperty.Access.WRITE_ONLY)
private String dishName;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接