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);
我有一个像这样的简单 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);