首页 > 解决方案 > 如何使用@JsonTypeInfo、@JsonSubType 根据兄弟字段的值确定字段类型?

问题描述

假设我有这样的班级结构:-

class ShapeRequest {

    ShapeInfo shapeInfo;
    Shape shape;

    static class ShapeInfo {
        String shapeName;
        String shapeDimension;
    }

    static abstract class Shape {

    }

    static class Square extends Shape{
        int area;
    }

    static class Circle extends Shape{
        int area;
    }
}

如何根据 shapeInfo.shapeName 字段值以字段 shape 映射到 Square 或 Circle 类型的方式反序列ShapeRequest ?

例如,下面的 JSON 应该映射到具有 Circle 形状类型的 ShapeRequest,因为 shapeInfo.shapeName = "circle"

{
  "shapeInfo": {
    "shapeName": "circle",
    "shapeDimension": "2"
  },
  "shape": {
    "area": 10
  }
}

标签: javaspringjacksonjackson-databindjackson2

解决方案


您可以在下面使用它:

public class JsonTypeExample {

    // Main method to test our code.
    public static void main(String args[]) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();

        // json to circle based on shapeName
        String json = "{\"shapeName\":\"circle\",\"area\":10}";
        Shape shape = objectMapper.readerFor(Shape.class).readValue(json);
        System.out.println(shape.getClass());
        System.out.println(objectMapper.writeValueAsString(shape));

        // json to square based on shapeName
        json = "{\"shapeName\":\"square\",\"area\":10}";
        shape = objectMapper.readerFor(Shape.class).readValue(json);
        System.out.println(shape.getClass());
        System.out.println(objectMapper.writeValueAsString(shape));
    }

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "shapeName")
    @JsonSubTypes({
            @JsonSubTypes.Type(value = Square.class, name = "square"),
            @JsonSubTypes.Type(value = Circle.class, name = "circle")
    })
    static class Shape {
        Shape() {
        }
    }

    @JsonTypeName("square")
    static class Square extends Shape {
        public int area;

        Square(int area){
            super();
            this.area = area;
        }
    }

    @JsonTypeName("circle")
    static class Circle extends Shape {
        public int area;

        Circle(int area){
            super();
            this.area = area;
        }
    }
}

这里 Shape 类使用 JsonTypeInfo 和 JsonSubTypes 进行注释。

@JsonTypeInfo 用于指示要包含在序列化和反序列化中的类型信息的详细信息。这里的属性表示确定 SubType 时要考虑的值。

@JsonSubTypes 用于表示注解类型的子类型。这里的namevalue将 shapeName 映射到适当的 SubType 类。

每当像示例中那样传递 JSON 时,都会通过 JsonSubTypes 进行反序列化,然后它会根据shapeName返回适当的 JAVA 对象。


推荐阅读