Вопрос

Для контекста мы храним большую часть наших данных в виде строк JSON.Это очень хорошо работает с Hadoop на внутренней стороне и легко обрабатывается на Ruby на внешней стороне.Мои типы данных соответствуют естественному шаблону наследования.

Для простоты предположим, что у меня есть класс Pet и процесс FeedPet, который кормит питомца.У меня также есть процесс WalkDog, который применяется только к собаке, которая является своего рода домашним животным.Мои данные организованы таким образом, что мне никогда не придется беспокоиться о том, чтобы выгуливать домашнее животное, кроме собаки.

Я хотел бы, чтобы Pet и Dog расширяли Pet, при этом у Dog был дополнительный метод getLeash(), но я не могу понять, как сопоставить это с JSON.

Вместо этого у меня есть класс Pet с хэш-картой данных о видах, поэтому процесс WalkDog будет вызывать pet.getSpeciesData("leash") вместо Dog.getLeash().

Я могу создать Dog расширяет Pet и сериализовать его в JSON, используя библиотеку Джексона.Объект JSON будет иметь поле поводка.Но предположим, что я хочу накормить всех домашних животных.У всех домашних животных есть метод getFood().Таким образом, процесс FeedPet десериализует объекты в Pet.Но при этом теряется поле поводка.

Процесс WalkDog может сделать это, поскольку он знает, что все его входные данные будут типа Dogs, поэтому он может прочитать их как Dog и записать обратно как Dog.

Есть ли способ сериализовать объекты Java в JSON, чтобы я мог сохранить их тип?Я думаю о чем-то вроде наследования одной таблицы в Rails, но это должно быть что-то, что понимают библиотеки JSON.

Это было полезно?

Решение

Чтобы это работало, вы должны как внедрить некоторую информацию о типе объекта в данные (где она полезна только для десериализации), так и обычно использовать внешнее определение схемы, которое в противном случае не было бы необходимо (например, XML-схема для xml;поскольку это по сути универсальная система типов).Это имеет те же проблемы, что и ORM:Hibernate должен использовать уродливые обходные пути (n+1-способ соединения, «супертаблицы» или поля дискриминатора).

Или еще один способ выразить это:Сопоставление/привязка данных — это не совсем то же самое, что сериализация/десериализация объекта (последняя пытается сохранить большую часть идентичности объекта).

Здесь я предполагаю, что вы хотите в основном что-то вроде:

Pet pet = mapper.readValue(jsonString, Pet.class);
// (and possibly get an exception if Pet is an abstract class...)
Leash l = ((Dog) pet).getLeash();

Если это не так, вы можете просто привязаться к Dog

Dog dog = mapper.readValue(jsonString, Dog.class);

В общем, как бы то ни было:Проект Джексона имеет запрос функции для выполнения именно этого, которые позволяют вам делать то, что (я думаю) вы хотите.

Однако это решение в основном будет работать для Java, поскольку не существует стандартного способа передачи информации о типе объекта в JSON.В XML это можно сделать с помощью атрибута «xsi:type», определенного в XML-схеме;который идентифицирует тип схемы, который затем сопоставляется с классом (да, довольно сложный способ, но он работает).

ОБНОВЛЯТЬ: Джексон 1,5 добавлена ​​поддержка этого (т.е.реализован запрос функции JACKSON-91), поэтому его можно использовать для генерации идентификаторов типов, чтобы обеспечить правильную обработку полиморфных типов.Он также должен работать с системами, отличными от Java, поскольку вы можете полностью настроить детали включения информации о типе;и НЕ ограничивается использованием имен классов Java.

Другие советы

У меня не было большого опыта использования JSON, кроме как для фиксации в django, но в этом случае у меня просто есть ключ «модели» с соответствующим значением.

Затем программа интерпретирует объекты, чтобы определить их тип и иерархию наследования.

Я пытаюсь сказать, что не имеет значения, какие методы доступны, поскольку их не нужно сериализовать.Только имя и атрибуты объекта.

-- обновлять

После повторного прочтения вашего вопроса кажется, что ваш процесс десериализуется в родительский класс, а не в реальный класс.Поскольку ваш класс собаки наследуется от класса pet, вам просто нужно убедиться, что ваш десериализатор создает объекты наиболее специализированного класса.

Я не знаю насчет библиотеки Джексона, но если вы можете настроить ее на тип поля модели, тогда это может быть подходящим вариантом.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top