data Thing = Thing {
thingName :: Text, -- E.g. "NW011"
thingVersion :: Text, -- I'm assuming that "Version" could include "1.2.3A" and hence should be a string, not a number.
thingCompatible :: [Text],
thingDescription :: Text
}
import qualified Data.HashMap.Strict as H
instance FromJSON [Thing] where
parseJSON (Object v) = mapM parseItem $ H.toList v
-- 'v' is a HashMap containing a key "NW011".
where
parseItem (k, Object v2) =
-- "v2" is a HashMap containing keys for the fixed field names ("version" etc.)
Thing k <$>
v2 .: "version" <*>
v2 .: "compatiblehardware" <*>
v2 .: "description"
import Data.Aeson
import Data.Text (Text)
import Data.HashMap.Strict as HMap
parseMyJSON :: Value -> Parser (Text,Value)
parseMyJSON (Object v) =
case HMap.toList v of
[(k,v)] -> (k, v)
_ -> fail "More than one key - who sent this thing?"
parseMyJSON _ = fail "Incorrect JSON - expected an object."
您可以将JSON解析为(Map Text Thing),其中Thing是您的记录类型。测试代码如下:
{-# LANGUAGE DeriveGeneric #-}
import Data.ByteString.Lazy as BSL
import Data.Text (Text)
import Data.Aeson
import Data.Map (Map)
import GHC.Generics
-- Record representing a single thing
data Thing =
Thing {
version :: Float,
compatiblehardware :: [Text],
description :: Text
} deriving (Show, Generic)
instance FromJSON Thing
main :: IO()
main = do
inh <- BSL.readFile "json.txt"
case decode inh :: Maybe (Map Text Thing) of
Just parsed -> print parsed
Nothing -> print "Unparsable"
3条答案
按热度按时间cbeh67ev1#
首先,需要声明一个数据类型来模拟数据的实际情况。我假设“NW011”实际上是一种字段,尽管所讨论的JSON格式已经将其提升为一个记录名。因此:
现在是示例。通常当你解析JSON时,你会有一个带有固定字段名的对象,所以你可以使用“.:“来提取它们。在这种情况下,你的最外层结构是一个单字段对象,其中的字段名为“NW011”,包含一个更传统的对象。
所以你需要写一个示例来检索这个原始对象。我假设你可能有几个这样的对象,它们有不同的名字,比如“NW012”等等,所以实际上你的外部结构是这些东西的一个列表。如果你解析你给出的例子,你会得到一个单元素列表。
在Aeson中,“Object”是一个查找表的 Package 器(即一个HashMap),所以你需要做的就是遍历HashMap,通过名称提取对象,所以答案应该看起来像这样(尽管我还没有尝试编译它):
注意,这里只给出了成功的例子,你的代码还应该包括parseJSON和parseItem的参数不是对象的例子。
t9aqgxwy2#
Aeson中的JSON对象只是散列Map。如果需要,可以提取所有键。在这种情况下,不能使用以JSON键命名的字段作为数据类型,因为这不一致,但仍然可以解析和使用JSON。下面是未经测试的代码。
dm7nw8vv3#
您可以将JSON解析为(Map Text Thing),其中Thing是您的记录类型。测试代码如下:
下面是测试数据“json.txt”: