Haskell JSON队列

时间:2017-12-11 16:45:18

标签: haskell

我想要一些Haskell的帮助,我对语言和函数式编程都很陌生(在JavaScript中已经接触过它,但没什么用)

我需要解析由参数定义的不同类型的JSON对象,并首先存储它们以供以后处理,例如:

{-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
import Data.Aeson
import Data.Text
import Control.Applicative
import Control.Monad
import qualified Data.ByteString.Lazy as B
import GHC.Generics
data Agent =
  Agent { agentId  :: Text
         , name   :: Text
         , primary_skillset  :: [Text]
         , secondary_skillset :: [Text]
           } deriving Show

instance FromJSON Agent where
 parseJSON (Object v) =
    Agent <$> v .: "id"
           <*> v .: "name"
           <*> v .: "primary_skillset"
           <*> v .: "secondary_skillset"
 parseJSON _ = mzero          

instance ToJSON Agent where
 toJSON (Agent agentId name primary_skillset secondary_skillset) =
    object [ "id"  .= agentId
           , "name"   .= name
           , "primary_skillset"        .= primary_skillset
           , "secondary_skillset" .= secondary_skillset
             ] 

jsonFile :: FilePath
jsonFile = "sample-input.json"  
-- Read the local copy of the JSON file.
getJSON :: IO B.ByteString
getJSON = B.readFile jsonFile   
main :: IO ()    
main = do
 -- Get JSON data and decode it
 d <- (eitherDecode <$> getJSON) :: IO (Either String [Agent])
 -- If d is Left, the JSON was malformed.
 -- In that case, we report the error.
 -- Otherwise, we perform the operation of
 -- our choice. In this case, just print it.
 case d of
  Left err -> putStrLn err
  Right ps -> print ps

这意味着我需要存储3种不同类型的数组,这些数组将来必须互相交互。

到目前为止,通过教程,我已经找到足够的指令,这使我能够使用fromJSON和toJSON打印一个对象的简单代码,我可以将其复制到其他对象,但我仍然不知道如何抓取对象通过第一个参数(new_agent,new_job,job_request),在决定如何解析之前:

#include <vector>
using namespace std;

struct TempData {
    vector<int> data;
    TempData() {
        for(int i = 0; i < 100; i++) data.push_back(i);
    }
    // vector<int> GetData() { // function 1
    //  return move(data);
    // }
    vector<int>&& GetData() { // function 2
        return move(data);
    }
};

int main() {
    vector<int> v;
    {
        TempData td;
        v = td.GetData();
    }
}

我正在寻找以下问题的答案(如果可能的话,还有代码片段):

  • 如何通过id抓取对象中的对象,然后将其添加到数组中

  • 将对象存储在数组中之后,我该如何&#34;迭代&#34;每当我需要再次使用那个特定信息时(通过对象键搜索)

  • 如何在数组中分配(更新)JSON,并将其保留在那里

1 个答案:

答案 0 :(得分:1)

下面的代码可以帮助您完成您想要做的事情。它使用与user2407038建议的技术类似的技术。将三种不同的数据类型收集到总和类型中:SomeObj。为SomeObj类型创建了三个不同的解析器,第一个成功的解析器是使用的 - 另外两个未使用。

如果可能,我让编译器自动定义JSON功能。

我添加了其他代码,通过转换回JSON然后解码该JSON来验证结果。

&#34; DuplicateRecordFields&#34;需要使用语言扩展程序,以便AgentJob都有id字段。

解析JSON后,您应该能够使用List功能来执行您所描述的搜索和更新操作。

{-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
{-# LANGUAGE DuplicateRecordFields #-}
import Data.Aeson
import Data.Text
import Control.Applicative
import Control.Monad
import qualified Data.ByteString.Lazy as B
import GHC.Generics

data Agent = 
    Agent { id :: Text
          , name :: Text
          , primary_skillset :: [Text]
          , secondary_skillset :: [Text]
          } deriving (Show, Generic)

instance FromJSON Agent
instance ToJSON Agent

data Job = 
    Job { id :: Text
        , tipo :: Text
        , urgent :: Bool
        } deriving (Show, Generic)

instance FromJSON Job
instance ToJSON Job

newtype JobRequest = 
    JobRequest { agent_id :: Text
               } deriving (Show, Generic)

instance FromJSON JobRequest
instance ToJSON JobRequest

data SomeObj = 
      AnAgent Agent
    | AJob Job
    | AJobRequest JobRequest
    deriving (Show, Generic)

newAgentTag = "new_agent"
newJobTag = "new_job"
jobRequestTag = "job_request"

instance FromJSON SomeObj where
  parseJSON (Object v) =
    let -- create multiple parsers.
        parseAgent = AnAgent <$> (v .: newAgentTag)
        parseJob = AJob <$> (v .: newJobTag)
        parseJobRequest = AJobRequest <$> (v .: jobRequestTag)
    in -- Use one of the collection of parsers.
        parseAgent <|> parseJob <|> parseJobRequest

  parseJSON _ = mzero

instance ToJSON SomeObj where
  toJSON (AnAgent agent) = object [newAgentTag .= agent]
  toJSON (AJob job) = object [newJobTag .= job]
  toJSON (AJobRequest jobRequest) = object [jobRequestTag .= jobRequest]

jsonFile :: FilePath
jsonFile = "sample-input.json"
-- Read the local copy of the JSON file.
getJSON :: IO B.ByteString
getJSON = B.readFile jsonFile
main :: IO ()
main = do
 -- Get JSON data and decode it
  d <- (eitherDecode <$> getJSON) :: IO (Either String [SomeObj])

  -- If d is Left, the JSON was malformed.
  -- In that case, we report the error.
  -- Otherwise, we perform the operation of
  -- our choice. In this case, just print it.
  case d of
    Left err -> putStrLn err
    Right ps -> do
      print ps

      -- convert back to JSON.
      let j2 = encode ps -- 
      print j2

      -- decode the newly converted JSON
      let d2 = eitherDecode j2 :: Either String [SomeObj]
      case d2 of
        Left err -> putStrLn err
        Right ps2 -> do
          print ps2