Десериализовать расширение класса TreeSet с помощью пользовательского компаратора с помощью GSON - PullRequest
1 голос
/ 27 марта 2019

У меня есть класс, который расширяет класс TreeSet.Его конструктор предоставляет пользовательский компаратор для TreeSet:

public class SortedPersonSet extends TreeSet<Person> {
    public SortedPersonSet(Comparator<Person> comp) {
        super(comp);
    }
}

Я хочу сериализовать и десериализовать этот класс, используя GSON, например:

SortedPersonSet personSet =
            new SortedPersonSet((p1, p2) -> Long.compare(p1.getAge(), p2.getAge()));
    personSet.add(new Person("Peter", 21));
    personSet.add(new Person("Klaus", 17));
    personSet.add(new Person("Martin", 27));
    personSet.add(new Person("John", 22));

// Serialize
Gson gson = new GsonBuilder().create();
String personSetAsString = gson.toJson(personSet);
System.out.println(personSetAsString);

// Deserialize
Gson gsonb = new GsonBuilder().create();
SortedPersonSet newPersons = gsonb.fromJson(personSetAsString, SortedPersonSet.class);
System.out.println(newPersons);

Однако эта версия выбрасываетисключение, потому что класс Person не реализует Comparable.

Итак, я попробовал подход, который помог здесь путем реализации пользовательского JsonDeserializer, который возвращает SortedPersonSet с пользовательским компаратором:

 public class SortedSetDeserializer implements JsonDeserializer<SortedPersonSet> {

    @Override
    public SortedPersonSet deserialize(JsonElement json, Type typeOfT,
            JsonDeserializationContext context) throws JsonParseException {
        return new SortedPersonSet((p1, p2) -> Long.compare(p1.getAge(), p2.getAge()));
    }
}

// Deserialization in main
Gson gsonb = new GsonBuilder()
                .registerTypeAdapter(SortedPersonSet.class, new SortedSetDeserializer()).create();

SortedPersonSet newPersons = gsonb.fromJson(personSetAsString, SortedPersonSet.class);
System.out.println(newPersons);

К сожалению,в моем коде все еще есть ошибка, потому что когда я десериализирую строку JSON с помощью SortedPersonSet newPersons = gsonb.fromJson(personSetAsString, SortedPersonSet.class);, результирующий SortedPersonSet будет пустым.Я надеюсь, что вы можете указать, где я допустил ошибку.Также будет полезен еще один (надеюсь, более простой) вариант.

Заранее спасибо!

1 Ответ

1 голос
/ 27 марта 2019

Результирующий набор пуст, потому что в пользовательском десериализаторе вы не анализируете массив;только создает новый набор и возвращает его.Простая реализация с реальным классом десериализации должна выглядеть так:

class SortedSetDeserializer implements JsonDeserializer<SortedPersonSet> {

    @Override
    public SortedPersonSet deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        SortedPersonSet people = new SortedPersonSet(Comparator.comparingLong(Person::getAge));
        if (json.isJsonArray()) {
            JsonArray array = json.getAsJsonArray();
            array.forEach(e -> {
                people.add(context.deserialize(e, Person.class));
            });
        }
        return people;
    }
}

С другой стороны, создание нового подтипа TreeSet не звучит хорошо.Если ваш Person класс будет реализовывать Comparable:

class Person implements Comparable<Person> {

    @Override
    public int compareTo(Person o) {
        return Long.compare(this.getAge(), o.getAge());
    }
}

Вы можете легко десериализовать этот массив в TreeSet:

Type type = new TypeToken<TreeSet<Person>>() {
}.getType();
TreeSet<Person> newPersons = gsonb.fromJson(personSetAsString, type);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...