使用Aeson解析嵌入式JSON

时间:2018-12-19 15:57:43

标签: haskell aeson

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

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

与埃森(Eeson)在Haskell。这是我的类型:

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}

很显然,FromJSON的{​​{1}}实例不起作用,因为它将其视为BaseType而不是用于解析的更多JSON。我试图找到一种在Value String实例中使用decodeEither的方法,但是这要求我做一些不可思议的事情才能将FromJSON BaseType转换为String,我觉得必须有一种更整洁的方式,可能与ByteString有关。

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

1 个答案:

答案 0 :(得分:2)

我想可能是这样(未经测试):

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}