Java 如何使用@JsonTypeInfo、@JsonSubType根据同级字段';s值多少?

Java 如何使用@JsonTypeInfo、@JsonSubType根据同级字段';s值多少?,java,spring,jackson,jackson-databind,jackson2,Java,Spring,Jackson,Jackson Databind,Jackson2,假设我有这样一个类结构:- class ShapeRequest { ShapeInfo shapeInfo; Shape shape; static class ShapeInfo { String shapeName; String shapeDimension; } static abstract class Shape { } static class Square extends Shap

假设我有这样一个类结构:-

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映射为方形或圆形,从而反序列化ShapeRequest

例如,以下JSON应该映射到具有圆形形状类型的ShapeRequest,因为shapeInfo.shapeName=“Circle”

您可以在下面使用它:

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用于指示序列化和反序列化中要包含的类型信息的详细信息。 此处属性表示确定子类型时要考虑的值

@JsonSubTypes用于指示注释类型的子类型。 在这里,名称和值将shapeName映射到相应的子类型类


只要像示例中那样传递JSON,就会通过JsonSubTypes进行反序列化,然后它会基于shapeName返回相应的JAVA对象。

感谢您的响应。但是,您错过了反序列化到包含shapeInfo和实际ShapeQuest的类ShapeRequest{}的全部要点。您可以分享一个示例,说明如何序列化/反序列化ShapeRequest?看起来您没有正确地构建问题陈述。把类型能指放在不同的地方并不理想。试着把它移到合适的位置。但不幸的是,这就是为什么它来自外部系统。我尝试了很多来实现你想要的,但这似乎是不可能的。可以将形状最大化设置为圆形/方形,但不能设置面积。这可以通过使用显式映射器实现:new ObjectMapper().readerFor(Shape.class).readValue(new ObjectMapper().writeValueAsString(ImmutableMap.of(“shapeName”,shapeInfo.getShapeName(),“area”,0))。。这应该在shapeInfo setter中调用,而忽略ShapeRequest中的shapesetter。我觉得这不容易实现,因为问题陈述与JsonSubTypes所支持的相反。
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;
        }
    }
}