Почему GSON использует поля, а не геттеры / сеттеры?

79

Почему GSON использует ТОЛЬКО поля (частные, общедоступные, защищенные)? Есть ли способ указать GSON использовать только геттеры и сеттеры?

Земзела
источник

Ответы:

96

Вообще говоря, когда вы сериализуете / десериализуете объект, вы делаете это для получения точной копии состояния объекта; Таким образом, вы обычно хотите обойти инкапсуляцию, обычно желаемую в объектно-ориентированном дизайне. Если вы не обойдете инкапсуляцию, возможно, не удастся получить объект, который после десериализации имеет такое же состояние, как и до сериализации. Кроме того, рассмотрите случай, когда вы не хотите предоставлять сеттер для определенного свойства. Как должна действовать сериализация / десериализация, если вы работаете через геттеры и сеттеры?

Крис Шаффер
источник
28
А как насчет «вычисляемых полей», которые мы хотели бы предоставить внешнему миру? Как вы думаете, я должен создавать поле и обновлять это поле каждый раз, когда я обновляю одно из полей POJO? Ух ...
Фредерик
2
@ Frédéric - Я просто указываю на трудности, возникающие при использовании методов получения и установки свойств для сериализации; Вычисленные свойства также вызовут свои собственные проблемы. Например, если вы передаете кому-то сериализованный объект, а затем они обновляют значение вычисленного свойства и возвращают его вам, как приложение должно обрабатывать десериализацию? Притворяться, что свойство не обновлялось, или генерировать исключение? Кроме того, если они обновляют свойства, на которых основано вычисляемое свойство, состояние объекта фактически недействительно, а чтение значения этого свойства однозначно неверно.
Крис Шаффер,
1
Я согласен с @ Frédéric; есть некоторые крайние случаи, которые заслуживают использования полей свойств. Я только что столкнулся с одним, где у меня есть массив байтов для объекта, который я хотел бы исключить и вместо этого вернуть String. Теперь мне осталось адаптировать объект через DTO.
Ричард Клейтон,
Вычисляемые / производные поля должны быть помечены, transientчтобы они не сериализовались и не пересчитывались по запросу.
BoffinBrain 06
14
Это нормально, если вариантом использования является сериализация Java в Java, но довольно распространенный вариант использования - предоставить объект Java в результате вызова API REST, в этом случае на стороне Java нам не нужна двухсторонняя идеальная сериализация, гораздо чаще мы хотим скрыть поля и сериализовать (и десериализовать, если / когда необходимо) определенные, часто вычисляемые во время выполнения, свойства.
Симоне Джанни
26

Есть ли способ указать GSON использовать только геттеры и сеттеры?

Еще нет.

Из проектной документации :

[T] вот и хорошие аргументы в пользу свойств. Мы намерены улучшить Gson в последней версии для поддержки свойств в качестве альтернативного сопоставления для указания полей Json. На данный момент Gson основан на полях.

Программист Брюс
источник
Что касается поддержки Gson для геттеров и сеттеров, последнее обновление этого списка рассылки гласит, что «[т] перспективы внедрения такой функции в Gson довольно низки ...» groups.google.com/forum/#!topic / google-gson / 4G6Lv9PghUY
Программист Брюс
Я не думаю, что не следует использовать геттеры и сеттеры, Крис Шаффер довольно хорошо объясняет это в этом ответе.
Sentry
4
Напишите собственный сериализатор / десериализатор, чтобы вы могли использовать любой метод, который хотите записать значения обратно в свой класс.
Дэйв Берч
2
Этот ответ очень старый, для таких ответов stackoverflow нужен «сборщик мусора».
Азим
@jb нет. Ответ все еще в силе.
9ilsdx 9rvj 0lo
0

Расплывчатый план того, как это работает в нашем приложении, заключается в том, что у нас есть много TypeAdapterреализаций - некоторые для конкретных объектов, подобных значению, а некоторые для объектов в стиле bean, где мы знаем, что логика JavaBeans будет работать. Затем мы наклеиваем все это на a GsonBuilderперед созданием Gsonобъекта.

К сожалению, GSON действительно хреново справляется с такими типами как Object[]. В основном мы видели это, когда пытались создать объект JSON для представления параметров метода. Чтобы решить эту проблему, нужно создать собственные TypeAdapterэкземпляры, отражающие методы. (Это означает, что вы в конечном итоге используете один Gsonэкземпляр для каждого метода, который собираетесь вызвать ...)

Трейказ
источник
Как бы вы разумно справились с десериализацией чего-либо в Object? Как бы вы хотели угадать, что это такое, чтобы десериализовать его?
9ilsdx 9rvj 0lo
Для Object или для полиморфного материала в целом они, возможно, могут иметь запись атрибута, адаптер которой первоначально сериализовал ее. Но по памяти я думаю, что даже очевидные вещи вроде {"a", 2, "b"} не десериализовались в Object [].
Trejkaz