Как терпеть неправильный тип аргумента в JSON с Джексоном? - PullRequest
0 голосов
/ 27 сентября 2019

Я интегрируюсь со сторонним API, который отвечает с таким объектом:

{
  "name": {
    "firstName": "John",
    "lastName": "Doe"
  }
}

Соответствующий класс Java выглядит следующим образом:

class Name {
    private String firstName;
    private String lastName;
}

Проблема: Когда предполагается, что имя null API возвращает пустую строку вместо null или пустой объект:

{
  "name": ""
}

Задание: Как это терпетьповедение на стороне клиента, имея в виду, что я вызываю API, используя RestTemplate и Jackson Spring?

Другими словами, как я могу сказать Джексону обрабатывать пустую строку, переданную в атрибут name, как ноль или как объект класса Name с нулевыми свойствами?

Примечание. Невозможно заставить API работать правильно.Я должен справиться с этим на моей стороне.

Ответы [ 3 ]

1 голос
/ 27 сентября 2019

Вы либо используете try / catch и обрабатываете ошибку.Или вы пишете свой собственный десериализатор, если вам приходится работать с разными сценариями.

Попробуйте Catch

Name name;
try {
    // Your restTemplate code, will throw Exception when cannot serialize
} catch (Execption e) {
    name = null;
}

Документы десериализатора: https://fasterxml.github.io/jackson-databind/javadoc/2.3.0/com/fasterxml/jackson/databind/JsonDeserializer.html

Пример того, как вы можете десериализовать (не проверено)

// On your class specify Deserialzer
@JsonDeserialize(using = YourNameClassDeserializer.class)
public class YourNameClass {
    // your class here
}

// Your Deserializer class
public class YourNameClassDeserializer extends StdDeserializer<Item> { 

    @Override
    public Item deserialize(JsonParser jp, DeserializationContext ctxt) 
      throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        // Use JsonNode to figure out what you are getting and create the object by yourself
        return new YourNameClass(firstName, lastName);
    }
}

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

0 голосов
/ 27 сентября 2019

Попробуйте это.Это должно работать.Я бы сказал, что вам нужно немного изменить модель Java.

@JsonDeserialize(using = NameDeserializer.class)
public class NameWrapper {
    private Name name;

    public NameWrapper() {
    }

    public NameWrapper(Name name) {
        this.name = name;
    }

    public Name getName() {
        return name;
    }

    public void setName(Name name) {
        this.name = name;
    }
}

Имя класса будет похоже на

public class Name {
    private String firstName;
    private String lastName;

    public Name() {
    }

    public Name(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

И, наконец, десериализатор

public class NameDeserializer extends JsonDeserializer {
    @Override
    public NameWrapper deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException 

{

        ObjectCodec oc = jsonParser.getCodec();
        JsonNode node = oc.readTree(jsonParser);
        if(node.get("name").get("firstName") == null && node.get("name").textValue().isEmpty())
                return null;
        else {
             String firstName = node.get("name").get("firstName").textValue();
             String lastName = node.get("name").get("lastName").textValue();

            return  new NameWrapper(new Name(firstName, lastName));
        }
    }
}

Это будет работать соба эти json's

{
  "name": {
    "firstName": "John",
    "lastName": "Doe"
  }
}

и

{
  "name": ""
}
0 голосов
/ 27 сентября 2019

Джексон имеет функцию десериализации для этого называется ACCEPT_EMPTY_STRINGS_AS_NULL_OBJECTS.При загрузке Spring вы можете включить это, включив следующее свойство в application.properties:

spring.jackson.deserialization.accept-empty-string-as-null-object=true

После этого Джексон будет десериализовать пустые строки как null.

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

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