在 URI 上定义 FromJSON
Defining FromJSON on URI
使用Network-URI和Aeson,我定义了以下FROMJson URI
。
简而言之,我正在尝试实现一个 JSON 解码器,要求:
{ "value" : X }
其中 X
是一个 JSON 字符串,对于 parseURI(X
).[=21= 计算结果为 Just
]
instance FromJSON URI where
parseJSON = withObject "URI" $ \v ->
case Data.HashMap.Lazy.lookup "value" v of
Just (String str) -> let unpacked = T.unpack str in
case parseURI unpacked of
Just uri -> pure uri
Nothing -> fail $ "String:" ++ unpacked ++ "is not a valid URI."
Just value -> typeMismatch "value" value
Nothing -> fail $ "JSON object does not have 'value' key."
但是,对于有效的 URI
,我的代码不起作用:
λ: >parseURI "http://www.foo.com"
Just http://www.foo.com
λ: >toJSON $ URI "http" Nothing "//www.foo.com" "" ""
String "http//www.foo.com"
λ: >fromJSON $ toJSON $ URI "http" Nothing "//www.foo.com" "" ""
Error "expected (), encountered String"
如何修复我的 FromJSON
实例?
您的实例需要一个形状为 { "value": "url" }
的 JSON 对象,但是您使用的 toJSON
实例显然会生成一个纯字符串,正如您的交互式输出清楚地表明的那样。
要使交互式会话中的最后一个表达式起作用,您需要使 To
和 From
实例对称:要么使 ToJSON
实例生成一个对象 { "value": "url" }
或使 FromJSON
实例需要一个纯字符串。
此外,顺便说一句,您的实例可以使用 .:
运算符以更短的方式表达:
instance FromJSON URI where
parseJSON = withObject "URI" $ \v -> do
mUri <- parseURI . T.unpack <$> v .: "value"
maybe (fail "Bad URI") pure mUri
使用Network-URI和Aeson,我定义了以下FROMJson URI
。
简而言之,我正在尝试实现一个 JSON 解码器,要求:
{ "value" : X }
其中 X
是一个 JSON 字符串,对于 parseURI(X
).[=21= 计算结果为 Just
]
instance FromJSON URI where
parseJSON = withObject "URI" $ \v ->
case Data.HashMap.Lazy.lookup "value" v of
Just (String str) -> let unpacked = T.unpack str in
case parseURI unpacked of
Just uri -> pure uri
Nothing -> fail $ "String:" ++ unpacked ++ "is not a valid URI."
Just value -> typeMismatch "value" value
Nothing -> fail $ "JSON object does not have 'value' key."
但是,对于有效的 URI
,我的代码不起作用:
λ: >parseURI "http://www.foo.com"
Just http://www.foo.com
λ: >toJSON $ URI "http" Nothing "//www.foo.com" "" ""
String "http//www.foo.com"
λ: >fromJSON $ toJSON $ URI "http" Nothing "//www.foo.com" "" ""
Error "expected (), encountered String"
如何修复我的 FromJSON
实例?
您的实例需要一个形状为 { "value": "url" }
的 JSON 对象,但是您使用的 toJSON
实例显然会生成一个纯字符串,正如您的交互式输出清楚地表明的那样。
要使交互式会话中的最后一个表达式起作用,您需要使 To
和 From
实例对称:要么使 ToJSON
实例生成一个对象 { "value": "url" }
或使 FromJSON
实例需要一个纯字符串。
此外,顺便说一句,您的实例可以使用 .:
运算符以更短的方式表达:
instance FromJSON URI where
parseJSON = withObject "URI" $ \v -> do
mUri <- parseURI . T.unpack <$> v .: "value"
maybe (fail "Bad URI") pure mUri