Пользовательский десериализатор для сопоставления строки с логическим значением - PullRequest
4 голосов
/ 24 апреля 2020

Я делаю внешний вызов через RestTemplate следующим образом:

ResponseEntity<Response> response = template.exchange("some.endpoint.com", HttpMethod.POST, request, MyClass.class);

API возвращает логическое значение в формате String следующим образом: ("0" или "1")

{
    "some_lengthy_key_name" : "1"
}

Я пытаюсь сопоставить этот ответ со следующим классом.

@Getter
@JsonDeserialize(builder = MyClass.MyClassBuilder.class)
@Builder
public class MyClass{
    @JsonProperty("some_lengthy_key_name")
    private final boolean isValid;
}

Похоже, Джексон этого не развлекает и выдает следующую ошибку (понятно):

Невозможно десериализовать значение типа boolean из строки «1», только «true» или «false» распознано.

Я не хочу go по пути захвата его как строки и затем изменив значение после. Вместо этого предпочитайте go для возможности запуска пользовательской десериализации и пошли на следующее:

public class Deserializer extends JsonDeserializer<Boolean> {
    @Override
    public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        return !"0".equals(parser.getText());
    }
}

Теперь я аннотировал поле в MyClass следующим образом:

@Getter
@JsonDeserialize(builder = MyClass.MyClassBuilder.class)
@Builder
public class MyClass{
    @JsonDeserialize(using = Deserializer.class)
    @JsonProperty("some_lengthy_key_name")
    private final boolean isValid
}

Но, к сожалению, это тоже не работает и выдает ту же ошибку. Могу ли я получить совет относительно того, что я делаю неправильно с этой пользовательской десериализацией? Спасибо.

Ответы [ 2 ]

2 голосов
/ 24 апреля 2020

Для этого вам не нужно настраивать десериализатор, просто переопределите свойство с помощью метода пользовательского установщика, а затем аннотируйте этот метод с помощью @JsonProperty. Другая нота Джексона использует getters и setters для сериализации и десериализации, поэтому вы не можете объявить переменные как final

@Getter
@Setter
class MyClass{

   private boolean isValid;

   @JsonProperty("some_lengthy_key_name")
   public void setIsValid(String value) {
      isValid = "1".equals(value);
   }
}

В Джексоне есть другой способ десериализации с использованием конструктора для предотвращения неизменности объекта, проверьте это для более информации

@Getter
@Setter
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public class MyClass{

   private final boolean isValid;

   public MyClass(@JsonProperty("some_lengthy_key_name") String name) {
      this.isValid = "1".equals(name);
}
0 голосов
/ 24 апреля 2020

Вы не можете использовать final и использовать тип Boolean вместо boolean

@Getter
@Setter
public class MyClass{
    @JsonDeserialize(using = Deserializer.class)
    @JsonProperty("some_lengthy_key_name")
    private Boolean isValid; //<= You did not use final, and use Boolean type instead of boolean
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...