Под «историческими данными» я имею в виду даты в качестве ключа и значение в этот день в качестве значения.
Например, часто правительственные институты или исследовательское подразделение универа собирают данные о землетрясениях, ливнях, движении рынка и т. Д. В этом формате
{
"Meta Data": {
"1: Country": "SomeCountry",
"2: Region": "SomeRegion",
"3: Latest Recording": "2018-11-16"
},
"EarthQuakes": {
"2018-11-16": {
"Richter": "5.2508"
},
"2018-11-09": {
"Richter": "4.8684"
},
"2018-11-02": {
"Richter": "1.8399"
},
...
...
...
"1918-11-02": {
"Richter": "1.8399"
}
}
Обычно в нем будет раздел «Метаданные», а другой будет содержать значения / данные.
Я, как новичок, знаю два способа разбора документов такого типа.
Либо вы используете общий анализ, показанный в документации Aeson, где вы определяете типы данных, подобные этому
Data MetaData = MetaData { country :: String, region :: String, latestRec :: String } deriving (Show, Eq, Generic)
Сделайте это экземпляром FromJSON
instance FromJSON MetaData where
parseJSON = withObject "MetaData" $
\v -> do
metaData <- v .: pack "Meta Data"
country <- metaData .: pack "1: Country"
region <- metaData .: pack "2: Region"
latestRec <- metaData .: pack "3: Latest Recording"
return MetaData{..}
С включенными расширениями RecordWildCard
и DeriveGenerics
.
Проблема, с которой я сталкиваюсь при таком подходе, заключается в том, что его нелегко реализовать в разделе «EarthQuakes».
Мне нужно определить каждую дату
earthQuakes <- v .: "EarthQuakes"
date1 <- earthQuakes .: "2018-11-16"
date2 <- earthQuakes .: "2018-11-06"
date3 <- earthQuakes .: "2018-11-02"
...
...
dateInfinity <- earthQuakes .: "1918-11-16"
Лучшим подходом было бы просто проанализировать все данные как значения JSON по умолчанию, расшифровав ссылку в Object
type
thisFunction = do
linksContents <- simpleHttp "somelink"
let y = fromJust (decode linksContents :: Object)
z = aLotOfFunctionCompositions y
return z
где aLotOfFunctionCompositions
вначале преобразует Object
в HashMap
с парами [(k, v)]
. Затем я бы отобразил функцию unConstruct
, чтобы получить значение из конструкторов по умолчанию, таких как
unConstruct (DefaultType value) = case (DefaultType value) of
DefaultType x -> x
и, наконец, вы получите хороший список!
Проблема этого подхода заключается в aLotOfFunctionComposition
.
Это всего лишь пример! Но на самом деле это может выглядеть так же безобразно и нечитаемо, как этот
let y = Prelude.map (\(a, b) -> (decode (encode a) :: Maybe String, decode (encode (snd (Prelude.head b))) :: Maybe String)) x
z = Prelude.map (\(a, b) -> (fromJust a, fromJust b)) y
a = Prelude.map (\(a, b) -> (a, read b :: Double)) z
b = Prelude.map (\(a, b) -> (Prelude.filter (/= '-') a, b)) a
c = Prelude.map (\(a, b) -> (read a :: Int, b)) b
Это фрагмент рабочего кода, который я сделал.
Итак, мой вопрос заключается в следующем: есть ли лучший / более чистый способ декодирования таких JSON-файлов, где у вас много ключей «даты», и вам нужно проанализировать их в работоспособные типы данных?