Как я могу разобрать вложенный JSON с помощью Genson? - PullRequest
0 голосов
/ 13 мая 2019

Я получаю результаты от REST API, это список объектов json, представляющих пользователей с вложенными объектами json внутри каждого пользователя.Моя проблема в том, что имена вложенных свойств не соответствуют свойствам бина, которые я получил в своем коде.Но они настолько неуместны, что я действительно не хочу оставлять имена вложенных свойств API ...

Я использую genson 1.5 с java 8 и lombok для своих bean-компонентов.Я попытался использовать простой десериализатор, а затем конвертер, но безуспешно.

Вот пример того, что я получаю от API:

[
   {
      "FirstName": "Jack",
      "LastName": "Sparrow",
      "Adress": {
                   "String1": "Toulon",
                   "String2": "France",
                   "String3": "83",
                }
   },
   {
      "FirstName": "I am",
      "LastName": "Groot",
      "Adress": {
                   "String1": "Marseille",
                   "String2": "France",
                   "String3": "13",
                }
   },
]

Вот бин, который я хочу получить какновый формат:

@Data
public class User {
   private String firstName;
   private String lastName;
   private String country; //this represents String2 from the API
}

Я уже пробовал эти решения:

  • Просто с помощью рекомендованной десериализации (ошибка, потому что не получается получить те же свойства из API по сравнению с моим bean-компонентом):
private Genson genson = new Genson();

public List<User> getUserList() {
   Response response = api.target(url)...get();
   List<User> users = genson.deserialize(response.readEntity(String.class), new GenericType<List<User>>(){});
   return users;
}
  • Использование преобразователя для получения тех же параметров, что и у моего компонента
private Genson genson = new GensonBuilder().withConverters(new UserConverter()).create();

public List<User> getUserList() {
   Response response = api.target(url)...get();
   List<User> users = this.genson.deserialize(response.readEntity(String.class), new genericType<List<User>>(){});
   return users;
}
public class UserConverter implements Converter<User> {

    public User deserialize(ObjectReader reader, Context ctx) throws Exception {
        User user = new User();
        reader.beginObject();

        while (reader.hasNext()) {
            reader.next();
            if ("FirstName".equals(reader.name())) {
                user.setFirstName(reader.valueAsString());
            } else if ("LastName".equals(reader.name())) {
                user.setLastName(reader.valueAsString());
            } else if ("Adress".equals(reader.name())) {
                reader.beginObject();
                while (reader.hasNext()) {
                    if ("String2".equals(reader.name())) {
                        user.setCountry(reader.valueAsString());
                    } else {
                        reader.skipValue();
                    }
                }
                reader.endObject();
            } else {
                reader.skipValue();
            }
        }

        reader.endObject();
        return user;
    }

    @Override
    public void serialize(User object, ObjectWriter writer, Context ctx) throws Exception {
        // TODO Auto-generated method stub

    }
}

Ошибка:

com.owlike.genson.JsonBindingException: Could not deserialize to type interface java.util.List
    at com.owlike.genson.Genson.deserialize(Genson.java:384)
    ...

Caused by: com.owlike.genson.stream.JsonStreamException: Illegal character at row 0 and column 660 expected } but read '{' !
    at com.owlike.genson.stream.JsonReader.newWrongTokenException(JsonReader.java:942)
    ...

Генсон приводит пример на http://genson.io/Documentation/UserGuide/#custom-serde, но они читают список целых чисел как значение, поэтому я попробовал вложенное время для вложенного json ...

Если у кого-то есть идеио том, как справиться с моей проблемой, большое спасибо!

Ответы [ 2 ]

1 голос
/ 13 мая 2019

@ eugen Спасибо за ваш ответ, я пробовал @JsonProperty над каждым из моих параметров bean-компонента, но, к сожалению, он не работал.

Затем пришел коллега, и мы добавили в UserConverter:

private GenericType<Map<String, String>> adressMap = new GenericType<Map<String, String>>() {};

и изменил второе время для:

else if ("Adress".equals(reader.name())) {
   user.string2Value((ctx.genson.deserialize(adressMap, reader, ctx)).get("String2"));
}

это на самом деле работает.

0 голосов
/ 13 мая 2019

Ваша проблема в том, что имя атрибутов в JSON отличается от того, что есть в коде. Обратите внимание, что в вашем JSON первая буква прописная.

У вас есть несколько вариантов: - переименуйте их в свой JSON - Переименуйте на стороне кода с помощью @JsonProperty("newname") или используя builder.rename(currentName, newName). - Реализуйте пользовательский PropertyNameResolver , который делегирует разрешение имени ConventionalBeanPropertyNameResolver , а затем просто меняет первую букву на верхний регистр.

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

Я рекомендую реализовать пользовательский преобразователь имен.

...