복붙노트

[SPRING] 잭슨은 스프링의 인터페이스 목록으로 객체를 비 직렬화한다.

SPRING

잭슨은 스프링의 인터페이스 목록으로 객체를 비 직렬화한다.

내가 redis에서 개체를 저장하고로드해야합니다.

객체에는 인터페이스 인 GrantedAuthority 목록이 포함됩니다.

public class UserAccountAuthentication implements Authentication {
    private List<GrantedAuthority> authorities;
    private boolean authenticated = true;
    ...
}

Jackson은 객체를 성공적으로 직렬화하지만 다음과 같은 예외를 사용하여 객체를 직렬화 해제하지 못합니다.

abstract types can only be instantiated with additional type information

다음과 같이 유형을 지정할 수 있음을 알고 있습니다.

@JsonTypeInfo(

GrantedAuthority는 Spring의 인터페이스이며 변경할 수 없기 때문에이 경우에는 할 수 없습니다.

직렬화 된 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);

아직도 운이 없다.

해결법

  1. ==============================

    1.사용자 지정 디시리얼라이저를 추가해야한다고 생각합니다.

    사용자 지정 디시리얼라이저를 추가해야한다고 생각합니다.

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

    }

    이건 내 아들이야.

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

    그런 다음 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);
    

    }

  2. from https://stackoverflow.com/questions/35724693/jackson-deserialize-object-with-list-of-springs-interface by cc-by-sa and MIT license