LINUX.ORG.RU

JSON десериализация и динамическая vs статическая типизация

 , , , ,


0

1

Как известно JSON пришёл из JavaScript, который является языком программирования с динамической типизацией и прототипной моделью данных. Грубо говоря там есть Object в который можно динамически добавлять всё что угодно - как поля, так и функции. В JavaScript вообще не нужно объявлять какую-то заранее известную дата модель. А вот в таких языках как Java, со статической типизацией, это делать надо. При этом возникает масса проблем.

Допустим у нас есть примерно следующая модель данных в Java:

public class Cage<T extends Animal> {
    private T animal;

    // boilerplate code omitted
}

Класс Animal является базовым классом и какой именно его потомок может оказаться в этом поле заранее не известно. Внутри JSON может прийти совершенно любое животное.

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

public class Cage<T extends Animal> {
    private List<T> animals;

    // boilerplate code omitted
}

Проблема такого кода ещё и в том, что тип T всё равно статический и поселить, например, кошек с собаками в один список не получится, даже если они ладят друг с другом в реальной жизни.

Если данные приходят в виде JSON, их десериализация в такие модели данных со статической типизацией становится нетривиальной и это основная проблема, которую я хотел бы обсудить. Для того, чтобы всё работало правильно рано или поздно приходится добавлять в этот JSON дополнительную информацию о типах. В случае примеров выше - информацию о том, какой именно потомок Animal используется в каждом конкретном элементе списка. Мало того, что усложняется JSON, так ещё и десериализацию, например для REST контроллера в Spring Boot, приходится делать нестандартной.

Как правильнее решить эту проблему? Отказаться от POJO в пользу вложеных Map-ов или какого-то иного динамического отображения JSON (например ObjectNode из библиотеки Jackson)? Вообще отказаться от Java и писать серверный код на JavaScript под node.js? Или отказаться от JSON в пользу какого-то другого формата, у которого метаданные являются обязательными? На ум приходит что-то типа SOAP. Все три подхода имеют массу недостатков. Или может быть существует какой-то четвёртый подход, о котором я не подумал?



Последнее исправление: hummer (всего исправлений: 1)
Ответ на: комментарий от fernandos

сколько мапперов и фабрик можно было написать за время этой темы

Джава-вэй. В любой непонятной ситуации пиши фабрику фабрик.

Nervous ★★★★★
()
Ответ на: комментарий от abcq

Ну вот в википедии написано, что JavaScript таки динамически типизирован, а не нестрого типизирован.

hummer
() автор топика

Для того, чтобы всё работало правильно рано или поздно приходится добавлять в этот JSON дополнительную информацию о типах

Ты не понял, зачем типы нужны. Типы – это не про типы данных в проводах между компами. Типы – это про то, что твой код может или не может обрабатывать.

hateyoufeel ★★★★★
()
Ответ на: комментарий от hummer

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

Если говорить точно - жс динамически типизированный язык со слабой типизацией. Джава статически типизированный язык с сильной типизацией. Питон динамически типизированный язык с сильной типизацией и т.д.

Это разные понятия вот и все.

abcq ★★
()
Ответ на: комментарий от abcq

валидация дает вам информацию о типах, которая и является камнем преткновения при десериализации из джсон, когда не понятно что в нем и каких типов.

О типах данных в Java эта валидация никакой информации не даёт.

hummer
() автор топика
Ответ на: комментарий от hummer

она и не должна давать какой-то информации о типах данных в джава. Вы валидируете жсон, относительно схемы, если валидация успешная то вы можете на основе этой схемы понять какие типы данных содержит джсон и соответственно на основе этого правильно его десерилизовать в нужные объекты в джаве имея знания о типах. У вас просто не возникнет ситуации когда пришел джсон, а в нем непойми что, у вас валидатор сверяясь со схемой такой джсон не пропустит.

abcq ★★
()
Ответ на: комментарий от fernandos

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

Ну не прямо откинуться, а просто использовать нечто более стандартизированное, чем поле type.

Это не убогость жабки, это специальные ограничения. Представьте, что к ооп-мании уровня «джава работает на 1 миллиарда устройств» добавится динамическая типизация и ко.

Получится Groovy.

hummer
() автор топика
Ответ на: комментарий от abcq

она и не должна давать какой-то информации о типах данных в джава. Вы валидируете жсон, относительно схемы, если валидация успешная то вы можете на основе этой схемы понять какие типы данных содержит джсон и соответственно на основе этого правильно его десерилизовать в нужные объекты в джаве имея знания о типах. У вас просто не возникнет ситуации когда пришел джсон, а в нем непойми что, у вас валидатор сверяясь со схемой такой джсон не пропустит.

Это путь к неоднозначностям.

hummer
() автор топика
Ответ на: комментарий от hummer

Звучит достаточно размыто, разверните мысль. Путь к неоднозначности это принимать не валидированные данные и на основе них пытаться состряпать объекты. Статическая строгая типизация тем и хороша что все «по полочкам», ну на худой конец хотя бы просто строгая типизация пусть и динамическая.

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

abcq ★★
()
Ответ на: комментарий от hummer

Для этого нужно либо обрамлять POJO соответствующими аннотациями из Jackson, либо писать дополнительные миксин классы на каждый такой POJO. Оба решения являются костылями и увеличивают вероятность ошибки.

Это стандартные варианты решения, почему это костыли?

Например легко ошибиться в том какое значение поля type соответствует какому POJO классу.

Ну напиши самый простой тест. Для таких нетривиальных маппингов это в любом случае полезно.

В случае с аннотациями у POJO ещё появляется и дополнительная зависимость от jackson-annotation. Если дата модель является библиотекой и шарится между проектами, придётся везде и всюду тащить и эту её зависимость.

Для маппинга с/в JSON используются отдельные классы, которые используются исключительно для маппинга. Если ты один и тот же класс используешь и для маппинга JSON и, например, для маппинга в БД, ты делаешь это неправильно. Даже если сейчас у тебя там один и тот же набор полей.

Legioner ★★★★★
()
Ответ на: комментарий от hummer

А у тебя в дипломе написано, что у тебя ВО, но по тебе не скажешь, что у тебя вообще образование есть

anonymous
()
Ответ на: комментарий от kiotoze

Интересно. Это может быть универсальной альтернативой REST API?

hummer
() автор топика
Ответ на: комментарий от anonymous

У тебя в истории болезни написано, что давно выписался из закрытого учреждения, но по тебе не скажешь, что выздоровел. До сих пор на людей кидаешься.

hummer
() автор топика
Ответ на: комментарий от fernandos

Это не убогость жабки, это специальные ограничения

Ну да, ну да:)

Интересно, сколько мапперов и фабрик можно было написать за время этой темы?

Можно было справиться за половину времени написания ОП.

crutch_master ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.