我正试图通过解决一些在线练习问题来适应一些haskell库。
我有一些输出此代码的代码
Object (fromList [("ABC", String "123")])
也可能是
Object (fromList [("123", String "ABC")])
Object (fromList [(String "123", String "ABC")])
Object (fromList [("123", "ABC")])
我需要提取的是"123"
使用类型为.:
的{{1}}提取给定键的值会引发此错误
(.:) :: FromJSON a => Object -> Text -> Parser a
我最好的猜测是,我将不得不编写一个解析器,但我不知道该如何去做或寻找什么。
产生错误的代码:
• Couldn't match type ‘Value’ with ‘HashMap Text Value’
Expected type: Object
Actual type: Value
像这样定义DataSet的地方
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"
如果我要更换
newtype DataSet = DataSet {
data1 :: Object
} deriving (Show, Generic)
仅
print $ (Data.List.head l) .: "ABC"
我知道
print $ (Data.List.head l)
答案 0 :(得分:2)
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字符串)。
答案 1 :(得分:0)
一种使事情脱离Value
类型的快速而肮脏的方法是
将Value
编码为ByteString
编码的类型为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。
答案 2 :(得分:0)
您可以通过以下几种方法从Object
数据类型中解开Value
构造函数。
您可以创建一个函数来展开:
unwrapValue :: Value -> Object
unwrapValue (Object x) = x
unwrapValue _ = error "No Object available"
请注意,此功能将返回错误,因为在某些情况下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