jackson 使用 spring 接口列表反序列化对象 [英] jackson deserialize object with list of spring's interface
问题描述
我需要从 redis 中保存和加载对象.
I need to save and load objects from redis.
该对象包含一个接口的 GrantedAuthority 列表(除其他外):
The object contains list of GrantedAuthority (among other things) which is an interface:
public class UserAccountAuthentication implements Authentication {
private List<GrantedAuthority> authorities;
private boolean authenticated = true;
...
}
Jackson 成功序列化了对象,但无法反序列化,出现以下异常:
Jackson successfully serializes the object but fails to deserialize it with the following exception:
abstract types can only be instantiated with additional type information
我知道我可以通过添加来指定类型:
I know that I can specify the type by adding:
@JsonTypeInfo(
但是在这种情况下我不能这样做,因为 GrantedAuthority
是 Spring 的一个接口,我无法更改它.
But I can't do it in this case because the GrantedAuthority
is an interface of Spring and I cannot change it.
序列化的json是:
{
"authorities": [
{
"authority": "ROLE_NORMAL_USER"
}
],
"authenticated": true,
"securityToken": {
"expiration": 1458635906853,
"token": "sxKi3Pddfewl2rgpatVE7KiSR5qGmhpGl0spiHUTLAAW8zuoLFE0VLFYcfk72VLnli66fcVmb8aK9qFavyix3bOwgp1DRGtGacPI",
"roles": [
"ROLE_NORMAL_USER"
],
"expired": false,
"expirationDateFormatted": "2016-03-22 08:38:26.853 UTC"
},
"name": "admin",
"expired": false
}
抽象的GrantedAuthority
只填充了SimpleGrantedAuthority
.
所以我试过:
objectMapper.registerSubtypes(SimpleGrantedAuthority.class);
仍然没有运气.
推荐答案
我觉得你需要添加一个自定义的解串器
I think you need to add a custom deserializer
public class UserAccountAuthenticationSerializer extends JsonDeserializer<UserAccountAuthentication> {
@Override
public UserAccountAuthentication deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
UserAccountAuthentication userAccountAuthentication = new UserAccountAuthentication();
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
userAccountAuthentication.setAuthenticated(node.get("authenticated").booleanValue());
Iterator<JsonNode> elements = node.get("authorities").elements();
while (elements.hasNext()) {
JsonNode next = elements.next();
JsonNode authority = next.get("authority");
userAccountAuthentication.getAuthorities().add(new SimpleGrantedAuthority(authority.asText()));
}
return userAccountAuthentication;
}
}
这是我的json
{"authenticated":true,"authorities":[{"authority":"role1"},{"authority":"role2"}],"details":null,"principal":null,"credentials":null,"name":null}
然后在你的 POJO 顶部
Then at the top of your POJO
@JsonDeserialize(using = UserAccountAuthenticationSerializer.class)
public class UserAccountAuthentication implements Authentication {
这是测试
@Test
public void test1() throws IOException {
UserAccountAuthentication userAccountAuthentication = new UserAccountAuthentication();
userAccountAuthentication.setAuthenticated(true);
userAccountAuthentication.getAuthorities().add(new SimpleGrantedAuthority("role1"));
userAccountAuthentication.getAuthorities().add(new SimpleGrantedAuthority("role2"));
String json1 = new ObjectMapper().writeValueAsString(userAccountAuthentication);
UserAccountAuthentication readValue = new ObjectMapper().readValue(json1, UserAccountAuthentication.class);
String json2 = new ObjectMapper().writeValueAsString(readValue);
assertEquals(json1, json2);
}
这篇关于jackson 使用 spring 接口列表反序列化对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!