问题
I'm a beginner trying to learn more about Haskell and Aeson by parsing some json files I find online.
I have a .json
that looks like this
"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
}
}
}
The file contains some information that I need, but mostly the ones I don't.
This is what I've tried so far
{-# 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
I know of several different ways of parsing the info
By parsing the file has
Aeson Value
orAeson Object
and applyingData.HashMap.Strict.toList
to convert it in[(k, v)]
. The trouble is that on a big file, this method gets really messy.By using several
unConstructor
functions which work like this
unConstruct (Constructor x) = case (Constructor x) of
Constructor x -> x
But same problem: it gets really unreadable and messy really fast.
That's why I want to parse the .json
file as shown in the code above.
But the parsing is failing somewhere in the code because I'm getting Nothing
as an output.
The .json
file seems to be fine since if I use
main = do
x <- decodeFileStrict location :: IO (Maybe Object)
print x
it works just fine, printing file's contents with appropriate default aeson data types.
What could I be doing wrong?
Edit: Implemented fix suggested by @danidiaz in the comments.
Error Msg: Left "Error in $.Abilities['someAbility']: key \"Ammo\" not present"
来源:https://stackoverflow.com/questions/53466541/haskell-aeson-parsing-nested-json-with-part-unnecessary-values