【问题标题】:Parsing embedded JSON with Aeson使用 Aeson 解析嵌入的 JSON
【发布时间】:2018-12-19 15:57:42
【问题描述】:

我正在尝试解析表单的嵌入 JSON

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

与 Aeson 在 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}

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

我怎样才能使它正常工作?

【问题讨论】:

  • 这不是可以用Aeson的标准DeriveGeneric机制解决的吗?
  • @MarkSeemann 我不确定这意味着什么,谷歌并没有吐出任何对“DeriveGeneric Aeson”有用的东西。您介意在某个地方解释或链接我吗?
  • @MarkSeemann 我认为这不能解决我的问题。它仍然给出一个“got String expected EmbeddedType”错误。
  • 这不是 aeson 派生的东西解决的问题。

标签: haskell aeson


【解决方案1】:

我猜应该是这样的(未经测试):

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}

【讨论】:

  • 你可以做 baz_ &lt;- o .: "baz" 并给 baz_ 输入 Text (aeson 无论如何都会解码)。这将保存case HM.lookup ....
  • 我认为无论如何您都必须明确调用decode。 (parseJSON 仍然需要您从某个地方获取Value
  • @Li-yaoXia withEmbeddedJSON 为你调用decode(好吧,eitherDecode,无论如何)。
  • 感谢您的帮助,代码有效,但您介意通过解释一些事情来帮助我吗?我对 Haskell 有点陌生,我不明白 1)你如何用 withObject 组合 withEmbeddedJSON,2)你使用 String 类型构造函数,以及 3)如何将 parseJSON 传递到withEmbeddedJSON 做我们想做的事。
  • @thesecretmaster 对于(1)你可能喜欢this question;对于 (2) 我查看了 withEmbeddedJSON 的来源,以了解它期望的输入;对于 (3) 类型推断选择 parseJSON :: Value -&gt; Parser EmbeddedType,因此它分派到您的其他实例以解析嵌入的 JSON。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
相关资源
最近更新 更多