Jackson-仅当json字段值与class属性值匹配时才允许格式化

ltskdhd1  于 7个月前  发布在  其他
关注(0)|答案(1)|浏览(67)

我有以下课程:

public abstract class Event {
    private final String eventId;

    public Event(String eventId) {
        this.eventId = eventId;
    }
}

public class EventA extends Event {
    private final String type = "eventA";

    @JsonCreator
    public EventA(@JsonProperty("eventId") String eventId) {
        super(eventId);
    }

    public String getType() {
        return type;
    }
}

public class EventB extends Event {
    private final String type = "eventB";

    @JsonCreator
    public EventB(@JsonProperty("eventId") String eventId) {
        super(eventId);
    }

    public String getType() {
        return type;
    }
}

问题是,现在我可以将两个类都转换为EventB,并将type=="eventA"type=="eventA"合并:

EventA eventA = new ObjectMapper().readValue(
    "{\"gameProposalId\":\"foo\", \"type\": \"eventA\"}",
    EventA.class);

// This will result in EventB with type=="eventA"
EventB eventB = new ObjectMapper().readValue(
    "{\"gameProposalId\":\"foo\", \"type\": \"eventA\"}",
    EventB.class);

有没有办法将json中type字段的值与你试图解析的类中type的默认值进行比较,如果不匹配就抛出异常?

jk9hmnmh

jk9hmnmh1#

在我看来,最好的解决方案是自定义格式化,这样:

事件解析器

public class EventDeserializer<T extends Event> extends StdDeserializer<T> {

    public EventDeserializer() {
        this(null);
    }

    public EventDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public T deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        // Node
        JsonNode node = jp.getCodec().readTree(jp);

        // Fields
        String eventId = node.get("gameProposalId").asText();
        String type = node.get("type").asText();

        // Automatically checks the type
        if (type.equals("eventA")) {
            return (T) new EventA(eventId);

        } else if (type.equals("eventB")) {
            return (T) new EventB(eventId);

        } else {
            return null;
        }
    }
}

EventDeserializer根据type字段自动检查类型
要使其工作,您需要更改类中的注解。这样:

事件

@JsonDeserialize(using = EventDeserializer.class)
public abstract class Event {
    private final String eventId;

    public Event(String eventId) {
        this.eventId = eventId;
    }
}

@JsonDeserialize注解指定了自定义解析器类。
所以现在你不需要@JsonCreator@JsonProperty注解:

事件A

public class EventA extends Event {
    private final String type = "eventA";

    public EventA(String eventId) {
        super(eventId);
    }

    public String getType() {
        return type;
    }
}

事件B

public class EventB extends Event {
    private final String type = "eventB";

    public EventB(String eventId) {
        super(eventId);
    }

    public String getType() {
        return type;
    }
}

现在,如果你尝试用type == "eventA"的JSON示例化一个EventB,它将抛出一个java.lang.ClassCastException

final String json = "{\"gameProposalId\":\"foo\", \"type\": \"eventA\"}";

// Instance the object normaly
EventA eventA = new ObjectMapper().readValue(json, EventA.class);

// Throws: java.lang.ClassCastException: EventA cannot be cast to EventB
EventB eventB = new ObjectMapper().readValue(json, EventB.class);

我希望它有帮助:)

相关问题