Как настроить ObjectMapper по умолчанию, используемый Spring для использования настраиваемого десериализатора при десериализации классов Spring - PullRequest
0 голосов
/ 23 июня 2019

Я хочу использовать свой собственный десериализатор в стандартном SpringMa ObjectMapper, когда у меня есть класс типа OAuth2AccessToken.Интерфейс помечен

JsonDeserialize(using = OAuth2AccessTokenJackson2Deserializer.class)

, и это то, что он использует в данный момент для десериализации, но я хочу использовать свой собственный.

До сих пор я создал свой собственный десериализатор

public class MyCustomDeserializer extends StdDeserializer<OAuth2AccessToken> {

public MyCustomDeserializer() {
    super(OAuth2AccessToken.class);
}

@Override
public OAuth2AccessToken deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
        JsonProcessingException {

    String tokenValue = null;
    String tokenType = null;
    String refreshToken = null;
    Long expiresIn = null;
    Set<String> scope = null;
    Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>();

    // TODO What should occur if a parameter exists twice
    while (jp.nextToken() != JsonToken.END_OBJECT) {
        String name = jp.getCurrentName();
        jp.nextToken();
        if (OAuth2AccessToken.ACCESS_TOKEN.equals(name)) {
            tokenValue = jp.getText();
        }
        else if (OAuth2AccessToken.TOKEN_TYPE.equals(name)) {
            tokenType = jp.getText();
        }
        else if (OAuth2AccessToken.REFRESH_TOKEN.equals(name)) {
            refreshToken = jp.getText();
        }
        else if (OAuth2AccessToken.EXPIRES_IN.equals(name)) {
            try {
                expiresIn = jp.getLongValue();
            } catch (JsonParseException e) {
                expiresIn = Long.valueOf(jp.getText());
            }
        }
        else if (OAuth2AccessToken.SCOPE.equals(name)) {
            scope = parseScope(jp);
        } else {
            additionalInformation.put(name, jp.readValueAs(Object.class));
        }
    }

    // TODO What should occur if a required parameter (tokenValue or tokenType) is missing?

    DefaultOAuth2AccessToken accessToken = new DefaultOAuth2AccessToken(tokenValue);
    accessToken.setTokenType(tokenType);
    if (expiresIn != null) {
        accessToken.setExpiration(new Date(System.currentTimeMillis() + (expiresIn * 1000)));
    }
    if (refreshToken != null) {
        accessToken.setRefreshToken(new DefaultOAuth2RefreshToken(refreshToken));
    }
    accessToken.setScope(scope);
    accessToken.setAdditionalInformation(additionalInformation);

    return accessToken;
}

private Set<String> parseScope(JsonParser jp) throws JsonParseException, IOException {
    Set<String> scope;
    if (jp.getCurrentToken() == JsonToken.START_ARRAY) {
        scope = new TreeSet<String>();
        while (jp.nextToken() != JsonToken.END_ARRAY) {
            scope.add(jp.getValueAsString());
        }
    } else {
        String text = jp.getText();
        scope = OAuth2Utils.parseParameterList(text);
    }
    return scope;
}

}

Мой собственный пользовательский класс, расширяющий DefaultOAuth2AccessToken

@com.fasterxml.jackson.databind.annotation.JsonDeserialize(using = MyCustomDeserializer.class)
public class MyCustomOAuth2AccessToken extends DefaultOAuth2AccessToken {

public MyCustomOAuth2AccessToken(String value) {
    super(value);
}

public MyCustomOAuth2AccessToken(OAuth2AccessToken accessToken) {
    super(accessToken);
}
}

, и в данный момент я регистрирую боб типа Jackson2ObjectMapperBuilderCustomizer, как этот

    @Bean
public Jackson2ObjectMapperBuilderCustomizer addCustomDeserialization() {
    return new Jackson2ObjectMapperBuilderCustomizer() {

        @Override
        public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
            SimpleModule m = new SimpleModule();
            m.addDeserializer(OAuth2AccessToken.class, new MyCustomDeserializer());
            jacksonObjectMapperBuilder.modules(m);
        }
    };
}

    @Bean
public OAuth2ClientContext getOAuth2ClientContext() {
    DefaultOAuth2ClientContext defaultOAuth2ClientContext = new DefaultOAuth2ClientContext();
    defaultOAuth2ClientContext.setAccessToken(new MyCustomOAuth2AccessToken("test"));
    return defaultOAuth2ClientContext;
}

Ответы [ 2 ]

0 голосов
/ 23 июня 2019

Чтобы настроить ObjectMapper глобально, просто создайте bean-компонент типа Jackson2ObjectMapperBuilder и используйте метод deserializerByType:

@Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
  return new Jackson2ObjectMapperBuilder()
           .deserializerByType(OAuth2AccessToken.class, new MyCustomDeserializer());
}

Справку по настройке ObjectMapper в SpringBoot можно найти здесь .

0 голосов
/ 23 июня 2019

Вы можете просто аннотировать свои классы десериализации с помощью @ JsonComponent . Аннотация позволяет нам предоставлять аннотированный класс в качестве сериализатора и / или десериализатора Джексона без необходимости добавлять его в ObjectMapper вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...