gpt4 book ai didi

json - 使用 Aeson 解析有问题的 JSON

转载 作者:行者123 更新时间:2023-12-03 23:17:41 25 4
gpt4 key购买 nike

我正在尝试解析 JSON 对象,这些对象通常具有以下形式

{
"objects": [a bunch of records that can assume a few different forms],
"parameters": [same deal],
"values": {
"k1": "v1",
"k2": "v2",
...
}
}

使用 Haskell 的 Aeson 库。这个任务的一部分很简单,因为 parametersvalues字段不需要任何自定义解析(因此似乎只需要 FromJSON 的一般派生实例),并且包含在与 objects 关联的数组中的大多数记录也不需要特殊解析。但是,解析 objects数组中的记录有一些部分。当单独考虑时,已经记录了解决方案,但一起提出了我还没有想出如何解决的问题。

现在, objects 中记录的可能变体和 parameters数组数量有限,通常包含相同的键;例如,它们都有一个“name”键或一个“id”键,等等。但是它们中的许多都有一个“类型”键,它是一个保留关键字,因此不能被一般地解析。这是第一个问题。

第二个问题是 objects 中记录的可能变体之一可以有一个键——“依赖”让我们说——它的值可以假设不同的类型。它可以是单个记录
{
"objects": [
{
"depends": {
"reference": "r1"
},
...
],
...
}

或记录列表
{
"objects": [
"depends": [
{"reference": "r1"},
{"reference": "r2"},
etc.
],
],
...
}

碰巧这是在转换为 Haskell 对象后我想以自定义方式操作的一个字段(最终我想将此类“依赖”引用的集合表示为 Data.Graph 图)。

我最初的尝试是创建一个巨大的记录类型,它包含 objects 的元素中的所有可能的键。和 parameters数组。像这样的东西:
{-# LANGUAGE DeriveAnyClass    #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}

import Data.Aeson
import GHC.Generics

data Ref = Ref
{ ref :: String
} deriving (Show, Generic, FromJSON, ToJSON)

data Reference
= Reference Ref
| References [Ref]
deriving (Show, Generic, FromJSON, ToJSON)

type MString = Maybe String -- I'm writing this a lot using this approach

data PObject = PObject
-- Each of the object/parameter records have these keys
{ _name :: String
, _id :: String

-- Other keys that might appear in a given object/parameter record
, _type :: MString
, _role :: MString
, _depends :: Maybe Reference

-- A bunch more
} deriving Show

instance FromJSON PObject where
parseJSON = withObject "PObject" $ \o -> do
_name <- o .: "name"
_id <- o .: "id"
_type <- o .:? "type"
_role <- o .:? "role"
_depends <- o .:? "depends"
-- etc.
return PObject{..}

最后,整个 JSON 对象将被表示为
data MyJSONObject = MyJSONObject
{ objects :: Maybe [PObject]
, parameters :: Maybe [PObject]
, values :: Maybe Object
} deriving (Show, Generic, FromJSON)

这一直有效,直到它尝试解析“依赖”字段,报告
"Error in $.objects[2].depends: key \"tag\" not present"

没有“标签”键,所以我不确定这意味着什么。我怀疑它与 FromJSON 的通用实例有关。为 RefReference .

我的问题:
  • 这个错误说明什么?到目前为止,在我学习 Haskell 的过程中,错误一直非常有帮助。这个不是。我需要为 parseJSON 中的“depends”键做一些特别的事情吗?功能?
  • 所有这些样板实际上是因为两个键——“类型”和“依赖”。有没有更优雅的方法来处理这些键?
  • 相关地,这是我第一个真正的 Haskell 项目的一部分,所以我有一个更一般的设计问题。有经验的 Haskellers 和 Aeson 用户,你会如何为这种类型的 JSON 布局你的类型和实例?我尝试列出 objects 的每个可能的变体/parameters记录为自己的独立类型,并且只写自定义 FromJSON那些具有“depends”或“type”键的实例,但这产生了更多的样板代码,无论如何都不能解决我遇到的任何其他问题。关于“最佳实践”、惯用用法等的一般指示将非常有用和赞赏。
  • 最佳答案

    There are no "tag" keys, so I'm not sure what this means. I suspect it has to do with the generic instances of FromJSON for Ref and Reference.



    那是对的。来自 default, aeson 将使用 defaultTaggedObject 对和类型进行编码。 References是和类型。因此,aeson 引入了一个标签来区分构造函数。你可以用一个简短的例子来试试:
    ghci> data Example = A () | B deriving (Generic,ToJSON)
    ghci> encode B
    "{\"tag\":\"B\",\"contents\":[]}"

    当您使用 _depends <- o .:? "depends" , Reference解析器找不到它的标签。您必须自己在那里编写一些解析代码。

    关于json - 使用 Aeson 解析有问题的 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46877222/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com