Одним из способов решения этой проблемы является сопоставление с шаблоном для конструкторов данных JSON , которые действительны для вашего набора данных, и выдают недопустимые для всех остальных.
Например, вы можете написать что-то подобное для этого конкретного поля, помня, что parseJSON
- это функция из Value -> Parser a
:
instance FromJSON Group where
parseJSON (Bool False) = Group <$> pure []
parseJSON (Array arr) = pure (Group $ parseListOfInt arr)
parseJSON invalid = typeMismatch "Group" invalid
parseListOfInt :: Vector Value -> [Int]
parseListOfInt = undefined -- build this function
Вы можете увидеть примерэто в Aeson docs , которые довольно хороши (но вы вроде как должны прочитать их несколько раз).
Я бы тогда, вероятно, определил отдельный запись для представления объекта верхнего уровня, в который входит этот ключ, и который полагается на общее извлечение, но у других может быть лучшее предложение там:
data GroupObj = GroupObj { group :: Group } deriving (Eq, Show)
instance FromJSON GroupObj
Одна вещь, которую всегда следует иметь в виду при работе с Aesonэто базовые конструкторы (из которых только 6) и базовые структуры данных (например, HashMap
для Object
и Vector
для Array
).
Например, в приведенном выше примере, когда вы сопоставляете шаблон с Array arr
, вы должны знать, что вы получаете Vector Value
в arr
, и у нас еще есть работа, чтобыпревратить это в список целых чисел, поэтому я оставил эту другую функцию parseListOfInt
выше, потому что я думаю, что это, вероятно, хорошее упражнение для ее построения?