2016-10-08 2 views
0

У нас есть существующий класс A, который ранее был единственным типом, который мог появиться в определенной позиции на выходе JSON нашей конечной точки API REST. Тем не менее, теперь я делаю это расширение общего базового класса B, так что в этой позиции на выходе может появиться целый ряд разных типов, все наследующие от B.Как добавить подсказки типа для класса с пользовательским сериализатором в lift-json?

Я добавил подсказку типа к Formats, но даже если методы Formats правильно посмотрели информацию типа подсказки в обоих направлениях, подсказки типа были проигнорированы при сериализации лифтом-json.

Оказалось, что причина, по которой лифт-json не добавлял поля типа подсказки в JSON, состоял в том, что в нашем примере Formats был настроен пользовательский сериализатор, настроенный для этого класса, и пользовательские сериализаторы переопределяют типы подсказок.

Итак, как у нас есть класс, у которого есть собственный сериализатор, и испускает и выводит подсказки типов, позволяющие однозначно идентифицировать его тип (как на клиентах, так и на серверах)?

ответ

0

Это не очень хорошо документировано больше, но TypeHints черты имеет два метода:

def deserialize: PartialFunction[(String, JObject), Any] = Map() 
def serialize: PartialFunction[Any, JObject] = Map() 

Эти методы могут быть переопределены при осуществлении TypeHints признака (или при расширении при условии реализации TypeHints по умолчанию), чтобы указать пользовательскую логику сериализации и десериализации для объектов JSON, которые заданы типами намеков. Стандартные реализации (см. Выше) - это фактически частичные функции, которые никогда не соответствуют чему-либо, поэтому они не имеют никаких эффектов.

Есть некоторые различия с deserialize и serialize методов в Serializer, который является то, что наш код был ранее с помощью:

  1. Эти методы не принимают Formats аргумент, что означает, что необходимо полагаться a Formats экземпляр, который находится в области.

  2. Они работают на JObject на стороне JSON конверсии, а не его надтипа JValue (очевидно, когда вы думаете об этом - потому что все, что имеет тип подсказки неизбежно должен быть JSON объект, а не строка или номер или что-то еще).

  3. Они не принимают параметр типа и работают только на Any на стороне Scala преобразований - это потому, что они обрабатывают только типы типов, которые требуют специальной логики сериализации в одной большой частичной функции.

  4. Вместо того, чтобы TypeInfo, частичная функция deserialize принимает String, который является значением поля типа подсказки.

Я думаю, что большинство из этих различий, потому что это старый код подъемной JSON, когда еще не существовал Serializer черта, и когда есть только один способ сделать пользовательские сериализации.

Так что сработало для меня было:

def typeHints(implicit formats: Formats) = new OurTypeHintsImpl( ...типа подсказка информации ... ) {

override def deserialize = {

case ("type-hint-for-A", o: JObject) => ... существующих десериализации кода ...

}

override def deserialize = {

case A( ... ) => ... существующих сериализации кода ...

}

и добавить еще один тип с обеими намеками типа и пользовательскими сериализациями логикой, было бы просто необходимо добавить одну новую case ветви к обеим выше.

При таком подходе правильные подсказки типов автоматически добавляются лифтом-json, но вы по-прежнему можете полностью настроить, как выполняется остальная сериализация и десериализация. Поэтому я считаю, что это самый удобный и подходящий подход для большинства случаев (но для этого требовалось немного рефакторинга). Также должно быть возможным переопределить тип намека в пользовательском Serializer, но зачем изобретать колесо?

Предупреждение: соответствие типов по типам по умолчанию имеет ограничения по отношению к родовым типам, но это не должно иметь для этого никакого значения - если вы не самостоятельно сериализуете общий тип, содержащийся в другом типе, а вместо этого объединяете его во внешний тип в JSON.

Смежные вопросы