Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
461 views
in Technique[技术] by (71.8m points)

java - jackson deserialize object with list of spring's interface

I need to save and load objects from redis.

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 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(

But I can't do it in this case because the GrantedAuthority is an interface of Spring and I cannot change it.


the serialized json is:

{
"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

}


the abstract GrantedAuthority is only filled with SimpleGrantedAuthority.

so i tried:

objectMapper.registerSubtypes(SimpleGrantedAuthority.class);

and still no luck.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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;
}

}

This is my json

{"authenticated":true,"authorities":[{"authority":"role1"},{"authority":"role2"}],"details":null,"principal":null,"credentials":null,"name":null}

Then at the top of your POJO

@JsonDeserialize(using = UserAccountAuthenticationSerializer.class)
public class UserAccountAuthentication  implements Authentication {

Here's the test

@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);

}


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...