使用Aeson解析嵌入式JSON



我正在尝试解析形式为的嵌入式JSON

{
"foo":"bar",
"baz":"{"somekey":"someval"}"
}

伊森在哈斯克尔。以下是我的类型:

data BaseType = BaseType { foo :: String, baz :: EmbeddedType } deriving(Show)
instance FromJSON BaseType where
parseJSON = withObject "BaseType" $ o -> do
foo <- o .: "foo"
baz <- o .: "baz"
return $ BaseType { foo=foo, baz=baz }
data EmbeddedType = EmbeddedType { somekey :: String }
instance FromJSON EmbeddedType where
parseJSON = withObject "EmbeddedType" $ o -> do
somekey <- o .: "somekey"
return $ EmbeddedType {somekey=somekey}

显然,BaseTypeFromJSON实例不起作用,因为它将其视为Value String,而不是更多的JSON供其解析。我试图在我的FromJSON BaseType实例中找到一种使用decodeEither的方法,但这需要我做一些黑魔法来从String转换为ByteString,我觉得必须有一种更整洁的方法,可能与withEmbeddedJSON有关。

我如何才能使其正确工作?

我想它会是这样的(未经测试(:

instance FromJSON BaseType where
parseJSON = withObject "BaseType" $ o -> do
foo <- o .: "foo"
bazText <- o .: "baz"
baz <- withEmbeddedJSON "EmbeddedType" parseJSON (String bazText)
return $ BaseType { foo=foo, baz=baz }

或者您可以考虑将对withEmbeddedJSON的调用移动到EmbeddedType实例中;那么o .: "baz"应该只在BaseType实例中工作,代价是不再拥有一个只进行EmbeddedType解析而不去字符串化的解析器的句柄:

instance FromJSON BaseType where
parseJSON = withObject "BaseType" $ o -> do
foo <- o .: "foo"
baz <- o .: "baz"
return $ BaseType { foo=foo, baz=baz }
instance FromJSON EmbeddedType where
parseJSON = withEmbeddedJSON "EmbeddedType" . withObject "EmbeddedType" $ o -> do
somekey <- o .: "somekey"
return $ EmbeddedType {somekey=somekey}

最新更新