Я новичок, пытающийся узнать больше о Haskell и Aeson, анализируя некоторые json-файлы, которые я нахожу в Интернете.
У меня есть .json
, который выглядит следующим образом
"Abilities": {
"Prime": {
"Ammo": 210,
"Available": true,
"Diposition": 3,
"Type": "Secondary",
"Class": "Pistols",
"NormalAttack": {
"Chance": 0.25,
"Streak": 2,
"Rate": 2.67,
"ShotType": "Hit-Scan",
"Damage": {
"Front": 15,
"Back": 15,
"Up": 120,
"Down": 40
},
"Status": 0.25
}
"Accuracy": 9.8,
"Reload": 3,
"Name": "Prime",
"Magazine": 16,
},
"Dual": {
"Name": "Dual",
"Available": true,
"Diposition": 4,
"Class": "Swords",
"Type": "Melee",
"NormalAttack": {
"Chance": 0.25,
"Streak": 3,
"Rate": 1.08,
"Damage": {
"Down": 35
},
"Status": 0.15
}
}
}
Файл содержит некоторую информацию, которая мне нужна, но в основном те, которые мне не нужны.
Это то, что я пробовал до сих пор
{-# LANGUAGE DeriveGeneric #-}
module Lib
( someFunc
) where
import Data.Aeson
import Data.HashMap.Strict as HS
import Data.Maybe
import Data.Text
import Data.Map.Strict
import GHC.Generics
location = "src/this.json"
someFunc :: IO ()
someFunc = putStrLn "someFunc"
data Abilities = Abilities { abilities :: Map String Ability } deriving (Generic, Show)
instance FromJSON Abilities where
parseJSON = withObject "Abilities" $
\v -> Abilities
<$> v .: pack "Abilities"
data Ability = Ability { ammo :: Double
, normalAttack :: Effect
, accuracy :: Double
, name :: String
, diposition :: Double
, reload :: Double
} deriving (Generic, Show)
instance FromJSON Ability where
parseJSON = withObject "Ability" $
\v -> Ability
<$> v .: pack "Ammo"
<*> v .: pack "NormalAttack"
<*> v .: pack "Accuracy"
<*> v .: pack "Name"
<*> v .: pack "Diposition"
<*> v .: pack "Reload"
data Effect = Effect { chance :: Double
, streak :: Double
, rate :: Double
, damage :: Damage
, status :: Double
} deriving (Generic, Show)
instance FromJSON Effect where
parseJSON = withObject "Effect" $
\v -> Effect
<$> v .: pack "Chance"
<*> v .: pack "Streak"
<*> v .: pack "Rate"
<*> v .: pack "Damage"
<*> v .: pack "Status"
data Damage = Damage { front :: Double
, back :: Double
, up :: Double
, down :: Double
} deriving (Generic, Show)
instance FromJSON Damage where
parseJSON = withObject "Damage" $
\v -> Damage
<$> v .: pack "Front"
<*> v .: pack "Back"
<*> v .: pack "Up"
<*> v .: pack "Down"
main = do
x <- eitherDecodeFileStrict location :: IO (Either String Abilities)
print x
Я знаю несколько разныхспособы синтаксического анализа информации
При анализе файла есть Aeson Value
или Aeson Object
и применение Data.HashMap.Strict.toList
для преобразования его в [(k, v)]
.Проблема в том, что в больших файлах этот метод очень запутан.
При использовании нескольких функций unConstructor
, которые работают следующим образом:
unConstruct (Constructor x) = case (Constructor x) of
Constructor x -> x
Но та же проблема: он становится действительно нечитаемым и очень грязным.
Вот почему я хочу проанализировать файл .json
, как показано в кодевыше.
Но где-то в коде происходит сбой, потому что я получаю Nothing
в качестве вывода.
Файл .json
выглядит нормально, так как если яиспользуйте
main = do
x <- decodeFileStrict location :: IO (Maybe Object)
print x
он работает просто отлично, печатая содержимое файла с соответствующими типами данных aeson по умолчанию.
Что я могу делать не так?
Редактировать: Реализовано исправление, предложенное @danidiaz в комментариях.
Сообщение об ошибке: Left "Error in $.Abilities['someAbility']: key \"Ammo\" not present"