如何从Haskell,Aeson的Value中取出HashMap(Object)?
How to get HashMap (Object) out of Value in Haskell, Aeson?
我正在尝试通过解决一些在线练习题来习惯一些 haskell 库。
我有一些输出这个的代码
Object (fromList [("ABC", String "123")])
也可能是
Object (fromList [("123", String "ABC")])
Object (fromList [(String "123", String "ABC")])
Object (fromList [("123", "ABC")])
我需要提取的是"123"
使用具有类型 (.:) :: FromJSON a => Object -> Text -> Parser a
的 .:
提取给定键的值会引发此错误
• Couldn't match type ‘Value’ with ‘HashMap Text Value’
Expected type: Object
Actual type: Value
我最好的猜测是我将不得不编写一个解析器,但我不知道如何去做或寻找什么。
产生错误的代码:
x <- (eitherDecode <$> simpleHttp url) :: IO (Either String DataSet)
case x of
Left er -> print er
Right an -> do
let l = S.toList (data1 an)
print $ l .: "ABC"
DataSet 的定义如下
newtype DataSet = DataSet {
data1 :: Object
} deriving (Show, Generic)
如果我要替换
print $ (Data.List.head l) .: "ABC"
只有
print $ (Data.List.head l)
我明白了
Object (fromList [("ABC", String "123")])
Object
是 Value
type
的几个构造函数之一
Haskell Constructor | JSON Syntax
Object | {"key": "value"}
String | "hello"
Number | 123
Array | [1, 2, 3]
请注意,在这种情况下,构造函数 Object
不是类型 Object
的构造函数。 [末尾注释。]
错误来自将 Value
传递给某个需要 Object
的函数。如果遇到任何其他情况,您将需要定义程序应该做什么。
或者因为您有 data1 an :: Object
,您可以在其中查找所需的密钥。我不确定 S.toList
的类型是什么,但您似乎将 Object
转换为 Value
,然后将其传递给需要对象的 .:
。
最后说明:Object (fromList [("ABC", String "123")])
是一个单一的值,一个对象和一个键值对。 fromList
是一种从对象的各个部分创建对象的方法(而不是通过解析 JSON 字符串)。
从 Value
类型中获取东西的一种快速而肮脏的方法是
将 Value
编码为 ByteString
encode 的类型为 encode :: ToJSON a => a -> ByteString
所以在你的代码中
...
case x of
Left er -> print er
Right an -> do
let l = S.toList (data1 an)
x = (encode . snd) l -- you can replace snd with fst if you want "ABC" instead of "123"
y = decode x :: Maybe (HashMap String String)
case y of
Nothing -> print "got nothing"
Just a -> print $ Data.HashMap.Strict.toList a
这将输出如下列表:
[("123")]
现在您可以使用简单的函数提取值。
希望对您有所帮助。
要了解更多关于如何更好地解析 JSON 文件,我建议 https://artyom.me/aeson 好好阅读。
这里有一些方法可以从 Value
数据类型中解包 Object
构造函数。
您可以创建一个函数来解包:
unwrapValue :: Value -> Object
unwrapValue (Object x) = x
unwrapValue _ = error "No Object available"
请注意此函数将 return 出错,因为有可能 Value
不是 Object
。
另外,不要因为 Object
既是 Value
的构造函数又是 aeson 的类型而感到困惑!
您也可以内联解包,但它也不安全,这意味着它可能会导致运行时错误。例如:
getNum :: Array -> Either String Scientific
getNum someArray = flip parseEither someArray $ \arr -> do
let Just (Object obj) = arr !? 1 -- Unsafe unwrap Object constructor from Value (also unwraps Just constructor from Maybe)
(Number num) <- obj .: "myNumber" -- Unsafe unwrap Number constructor from Value
return num
我正在尝试通过解决一些在线练习题来习惯一些 haskell 库。
我有一些输出这个的代码
Object (fromList [("ABC", String "123")])
也可能是
Object (fromList [("123", String "ABC")])
Object (fromList [(String "123", String "ABC")])
Object (fromList [("123", "ABC")])
我需要提取的是"123"
使用具有类型 (.:) :: FromJSON a => Object -> Text -> Parser a
的 .:
提取给定键的值会引发此错误
• Couldn't match type ‘Value’ with ‘HashMap Text Value’
Expected type: Object
Actual type: Value
我最好的猜测是我将不得不编写一个解析器,但我不知道如何去做或寻找什么。
产生错误的代码:
x <- (eitherDecode <$> simpleHttp url) :: IO (Either String DataSet)
case x of
Left er -> print er
Right an -> do
let l = S.toList (data1 an)
print $ l .: "ABC"
DataSet 的定义如下
newtype DataSet = DataSet {
data1 :: Object
} deriving (Show, Generic)
如果我要替换
print $ (Data.List.head l) .: "ABC"
只有
print $ (Data.List.head l)
我明白了
Object (fromList [("ABC", String "123")])
Object
是 Value
type
Haskell Constructor | JSON Syntax
Object | {"key": "value"}
String | "hello"
Number | 123
Array | [1, 2, 3]
请注意,在这种情况下,构造函数 Object
不是类型 Object
的构造函数。 [末尾注释。]
错误来自将 Value
传递给某个需要 Object
的函数。如果遇到任何其他情况,您将需要定义程序应该做什么。
或者因为您有 data1 an :: Object
,您可以在其中查找所需的密钥。我不确定 S.toList
的类型是什么,但您似乎将 Object
转换为 Value
,然后将其传递给需要对象的 .:
。
最后说明:Object (fromList [("ABC", String "123")])
是一个单一的值,一个对象和一个键值对。 fromList
是一种从对象的各个部分创建对象的方法(而不是通过解析 JSON 字符串)。
从 Value
类型中获取东西的一种快速而肮脏的方法是
将 Value
编码为 ByteString
encode 的类型为 encode :: ToJSON a => a -> ByteString
所以在你的代码中
...
case x of
Left er -> print er
Right an -> do
let l = S.toList (data1 an)
x = (encode . snd) l -- you can replace snd with fst if you want "ABC" instead of "123"
y = decode x :: Maybe (HashMap String String)
case y of
Nothing -> print "got nothing"
Just a -> print $ Data.HashMap.Strict.toList a
这将输出如下列表:
[("123")]
现在您可以使用简单的函数提取值。
希望对您有所帮助。
要了解更多关于如何更好地解析 JSON 文件,我建议 https://artyom.me/aeson 好好阅读。
这里有一些方法可以从 Value
数据类型中解包 Object
构造函数。
您可以创建一个函数来解包:
unwrapValue :: Value -> Object
unwrapValue (Object x) = x
unwrapValue _ = error "No Object available"
请注意此函数将 return 出错,因为有可能 Value
不是 Object
。
另外,不要因为 Object
既是 Value
的构造函数又是 aeson 的类型而感到困惑!
您也可以内联解包,但它也不安全,这意味着它可能会导致运行时错误。例如:
getNum :: Array -> Either String Scientific
getNum someArray = flip parseEither someArray $ \arr -> do
let Just (Object obj) = arr !? 1 -- Unsafe unwrap Object constructor from Value (also unwraps Just constructor from Maybe)
(Number num) <- obj .: "myNumber" -- Unsafe unwrap Number constructor from Value
return num