【问题标题】:Jackson subtypes - how to specify a defaultJackson 子类型 - 如何指定默认值
【发布时间】:2026-01-08 01:10:01
【问题描述】:

我想对子类型做这样的事情。 我有 3 种不同类型的对象:

{
  "value": "string"
}

{
  "value": {
    "type": "obj1"
  }
}

{
  "value": {
    "type": "obj2"
  }
}

value 可以是字符串或对象。

对应的Java类是

public interface Value {
}

public class ValueString implements Value {
    String value;
}

public abstract class ValueObj implements Value{
    public String type;
}

public class ValueObj1 extends ValueObj {
    private Obj1 value;
}

public class ValueObj2 extends ValueObj {
    private Obj2 value;
}

我不介意在 Obj1 和 Obj2 中使用鉴别器,但是当值只是一个字符串时,就没有鉴别器了。有没有一种方法可以设置它,如果值是字符串,则反序列化为 ValueString,但如果它是对象,则反序列化为正确的 ValueObj1 或 ValueObj2?

【问题讨论】:

    标签: java json jackson polymorphism


    【解决方案1】:

    可以通过先创建自定义反序列化器轻松完成:
    p.s.我假设您发布的对象只有三种类型。

    public class ValueDeserializer extends StdDeserializer<Value> {
        public ValueDeserializer() {
            this(null);
        }
    
        protected ValueDeserializer(Class<?> vc) {
            super(vc);
        }
    
        @Override
        public Value deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException {
            JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser);
            if (jsonNode.get("value").isValueNode()) {
                return new ValueString(jsonNode.get("value").asText());
            } else if ("obj1".equals(jsonNode.get("value").get("type").asText())) {
                ValueObj1 valueObj1 = new ValueObj1();
                    
                // The logic to handle type obj1
                    
                return valueObj1;
            } else {
                ValueObj2 valueObj2 = new ValueObj2();
    
                // The logic to handle type obj2
                    
                return valueObj2;
            }
    }
    

    然后简单地用@JsonDeserialize注释类Value如下:

    @JsonDeserialize(using = ValueDeserializer.class)
    public interface Value {
    }
    

    最后,让Jackson 为您完成剩下的工作:

    ObjectMapper objectMapper = new ObjectMapper();
    System.out.println(objectMapper.writeValueAsString(objectMapper.readValue(jsonStr, Value.class)));
    

    【讨论】: