Haskell, Aeson: анализ вложенного JSON с ненужными значениями части - PullRequest
0 голосов
/ 25 ноября 2018

Я новичок, пытающийся узнать больше о 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

Я знаю несколько разныхспособы синтаксического анализа информации

  1. При анализе файла есть Aeson Value или Aeson 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"

...