Hasesell,Aeson:使用部分不必要的值解析嵌套的JSON

时间:2018-11-25 10:19:26

标签: json parsing haskell aeson

我是一个初学者,试图通过解析一些我在网上找到的json文件来了解有关Haskell和Aeson的更多信息。

我有一个.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

我知道几种解析信息的方式

  1. 通过分析文件具有Aeson ValueAeson Object并应用Data.HashMap.Strict.toList将其转换为[(k, v)]。麻烦的是,在大文件上,此方法会变得非常混乱。

  2. 使用几个像这样工作的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"

0 个答案:

没有答案