. Изначальный Ваш посыл ведь был в том, что «статические языки впадают в ступор».
Как видно, никакой проблемы работать с объектами неизвестной структуры нет. Правда, что полезного можно сделать с такими объектами?!.. Наверняка, у вас есть хотя бы частичные представления о структуре (например, должны присутствовать поля «foo», «bar», опционально «baz», ну и хрен его знает что еще). Никакой проблемы описать тип:
data MyFancyData = MyFancyData
{ foo :: Int
, bar :: Text
, baz :: Maybe Bool
, fields :: HashMap Text Value
}
instance FromJSON MyFancyData where
parseJSON = withObject "MyFancyData" $ \obj ->
MyFancyData <$> (obj .: "foo") <*> (obj .: "bar") <*> (obj .:? "baz") <*> pure obj
instance ToJSON MyFancyData where
toJSON = Object . fields
У вас есть почти бесплатно сериализатор/десериализатор+валидатор, а также доступ ко всем полям исходного JSON объекта. Это элементарно обобщить до
data WithRawObject a =
{ decodedVal :: a
, rawObject :: HashMap Text Value
}
instance (FromJSON a) => FromJSON (WithRawObject a) where
parseJSON = withObject "Raw" \obj ->
WithRawObject <$> parseJSON (Object obj) <*> pure obj
И теперь это будет работать с любым типом, для которого определен JSON десериализатор.
data MyFancyData = MyFancyData
{ foo :: Int
, bar :: Text
, baz :: Maybe Bool
} deriving (Generic, FromJSON)
main = do
bs <- queryAPI
case eitherDecode bs of
Left e -> error e -- Например, поле "foo" отсутствует. Ну или это вообще не JSON
Right (WithRawObject (MyFancyData foo_val bar_val baz_val) fields) ->
doSmth1 foo_val bar_val baz_val
doSmth2 fields
в интернете кто-то неправне люблю когда так безапелляционно утверждают очевидную чушь.Как видно, никакой проблемы работать с объектами неизвестной структуры нет. Правда, что полезного можно сделать с такими объектами?!.. Наверняка, у вас есть хотя бы частичные представления о структуре (например, должны присутствовать поля «foo», «bar», опционально «baz», ну и хрен его знает что еще). Никакой проблемы описать тип:
У вас есть почти бесплатно сериализатор/десериализатор+валидатор, а также доступ ко всем полям исходного JSON объекта. Это элементарно обобщить до
И теперь это будет работать с любым типом, для которого определен JSON десериализатор.
А в чем ступор?
let dict = decode @(HashMap Text Value) s
А дальше то же, что в динамике