Jackson 反序列化仅提供一个 @Id 作为字符串

Jackson deserialization by only providing an @Id as a String

我有一个像这样的简单 class :

public class User {
  @Id
  private Integer id;
  private String name;
   ...
}

显然可以用Jackson直接反序列化这个JSON:

{
  "id": 123  // with int
  "name": "bli",
}

{
  "id": "123"  // with String
  "name": "bli",
}

但是,@Id 注释似乎默认提供了仅通过提供 Id 来反序列化 User class 的可能性。例如,假设我有另一个 class Search 包含 User:

public class Search {
  private String title;
  private User user;
   ...
}

这个有效:

{
  "title": "blo",
  "user": 123 // with int
}

但不是这个:

{
  "title": "blo",
  "user": "123" // with String
}

有没有办法通过仅提供字符串形式的 id 来允许对 class 进行反序列化?


注意:我所有的 classes 都通过 Hibernate 绑定到 Postgres 数据库。因此 @Id 注释。我故意忽略了这里的其他注释,它似乎不相关。

好的,自定义反序列化器将是:

public class UserDeserializer extends StdDeserializer<User> implements ResolvableDeserializer {

    private final JsonDeserializer<?> defaultDeserializer;

    public UserDeserializer(JsonDeserializer<?> defaultDeserializer) {
        super(User.class);
        this.defaultDeserializer = defaultDeserializer;
    }

    @Override
    public User deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
        String text = jp.getText();
        JsonToken currentToken = jp.getCurrentToken();

        if(!currentToken.equals(JsonToken.VALUE_NUMBER_INT) && !text.startsWith("{")) {
            try{
                return new User(Integer.parseInt(text));
            }
            catch(Exception e) {
                throw new IOException("Unable to process '" + text + "'. Expecting an ID as an integer or a full json representation of the object.");
            }

        }

        return (User) defaultDeserializer.deserialize(jp, dc);
    }

    @Override
    public void resolve(DeserializationContext ctxt) throws JsonMappingException {
        ((ResolvableDeserializer) defaultDeserializer).resolve(ctxt);
    }
}

SimpleModule module = new SimpleModule();
module.setDeserializerModifier(new BeanDeserializerModifier() {
    @Override
    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
        if (beanDesc.getBeanClass() == User.class)
            return new UserDeserializer(deserializer);
        return deserializer;
    }
});
environment.getObjectMapper().registerModule(module);