当前位置: 首页 > 面试题库 >

如何使用Swift的Decodable解析一个仅知道或关心几个字段的任意JSON字符串?

邹嘉致
2023-03-14
问题内容

新的Swift“ Decoder”类听起来像是解析JSON数据的好方法,但是我发现的所有示例都使用众所周知的,定义明确的’struct’来实现。

在我的情况下,我正在查询返回巨大JSON字符串的任意网站,并且我只关心几个(深度嵌套)字段,所以我不想花所有时间定义一个“结构”来获取在他们。

甚至可以通过“解码器”来做到这一点吗?如果是这样,该如何处理?


问题答案:

这个问题似乎是基于对“可分解的东西”如何工作的误解。为方便起见,Decodable愿意在幕后进行一些自动代码生成,以便您 可以
定义结构或结构嵌套,并仅解码整个JSON。但是您 不需要 利用它来解码JSON。

  • 无需为不需要的“字段”定义结构属性。如果JSON字典包含100个键,而您的对应结构仅包含一个属性,则没有问题;该密钥将被获取,没有其他密钥。

  • 关于“深度嵌套”部分,您应该花很多时间来编写简单的嵌套结构,这些结构执行潜水才能到达您真正关心的字典。但是,即使您不想这样做,也可以编写一个实现的init(from:)摘要,然后取出所需的值。

换句话说,如果您认为Decodable 主要
由的实现组成init(from:),并学习编写所需的代码,则将看到可以用几行简单的代码行来解析此JSON。

举例来说,这是一个深层嵌套的信息的JSON草图,在每个层次上我们都忽略了很多额外的信息:

{
  "ignore": true,
  "outer1": {
    "ignore": true,
    "outer2": {
      "ignore": true,
      "outer3": {
        "name": "matt",
        "ignore": true
      }
    }
  }
}

我想做的是定义一个非常简单的struct Person,它仅由深层嵌套组成name

struct Person : Decodable {
    let name : String
}

我可以做到的!为此,我自己实现了Decodable,提供了一个“
hoover”的CodingKey采用者结构和的实现init(from:),这样(这看起来像很多工作,但不是,因为AnyCodingKey实现是样板化,复制并粘贴的)从这里开始,init(coder:)实现只是几行易于编写的代码):

    struct Person : Decodable {
        let name : String
        struct AnyCodingKey : CodingKey {
            var stringValue: String
            var intValue: Int?
            init(_ codingKey: CodingKey) {
                self.stringValue = codingKey.stringValue
                self.intValue = codingKey.intValue
            }
            init(stringValue: String) {
                self.stringValue = stringValue
                self.intValue = nil
            }
            init(intValue: Int) {
                self.stringValue = String(intValue)
                self.intValue = intValue
            }
        }
        init(from decoder: Decoder) throws {
            var con = try! decoder.container(keyedBy: AnyCodingKey.self)
            con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer1"))
            con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer2"))
            con = try! con.nestedContainer(keyedBy: AnyCodingKey.self, forKey: AnyCodingKey(stringValue:"outer3"))
            let name = try! con.decode(String.self, forKey: AnyCodingKey(stringValue:"name"))
            self.name = name
        }
    }

当我想深入研究JSON并获取name信息时,这很简单:

let person = try! JSONDecoder().decode(Person.self, from: json)

结果是一个带有namevalue 的Person对象"matt"。注意,我不必添加任何ignore键,也不需要嵌套结构。



 类似资料:
  • 问题内容: 新的Swift“ Decoder”类听起来像是解析JSON数据的好方法,但是我发现的所有示例都使用众所周知的,定义明确的’struct’来实现。 在我的情况下,我正在查询返回巨大JSON字符串的任意网站,并且我只关心几个(深度嵌套)字段,所以我不想花所有时间定义一个“结构”来获取在他们。 甚至可以通过“解码器”来做到这一点吗?如果是这样,该如何处理? 问题答案: 这个问题似乎是基于对“

  • 无法弄清楚如何将以下带有GSON的JSON字符串解析为任何适当的对象以检索其数据。字符串是: 我发现方括号表示它是一个ArrayList,但里面还有另一个对象。 如果我试着在ArrayList上搜索: 然后它抱怨: 如果我尝试相反的方法: 然后它也在抱怨: 不理解该格式:-/ 感谢您的任何建议!

  • 需要验证的字符串采用以下格式,严格来说它不是JSON,不能使用PHP的JSON编码过程进行验证。请注意,键中的%%是必需的。 当前正则表达式成功验证了上述内容: 有效示例:https://regex101.com/r/4y1uEu/1 无效示例(第二个值周围没有引号):https://regex101.com/r/4y1uEu/2 值需要支持其他字符,最好是任何字符,所以我将REGEX更改为 与此

  • 问题内容: 但是现在我想改善对带有多个对象的JSON字符串的解码,但我不知道该怎么做。 这是一个例子: 如何仅使一个foreach()解码以上JSON字符串? 如何检测对象的名称:此foreach()上的收件箱,已发送或草稿? 问题答案: 新答案 重新修改后的问题:实际上适用于属性以及多值项(数组),请参见此处。例如,在您的问题中包含JSON字符串: 在属性的主循环内,可以使用内部循环遍历每个属性

  • 问题内容: 我有与此类似的JSON: 我创建了一些类来映射这个json 而Model1类是仅包含String字段的简单类。 但这是行不通的。 编辑:JSON格式如下所示: 问题答案: Gson 2.0+的解决方案 我刚刚了解到,使用更新的Gson版本,这非常简单: 创建的对象是一个Map(com.google.gson.internal.LinkedTreeMap),如果你打印它,它看起来像这样:

  • 问题内容: 我正在尝试制作一个自动更正系统,并且当用户键入一个带有大写字母的单词时,自动更正不起作用。为了解决此问题,我复制了键入的字符串,并应用了.lowercaseString,然后对其进行了比较。如果确实输入了错误的字符串,则应更正单词。但是,替换键入的单词的单词全部为小写。所以我只需要将.uppercaseString应用于第一个字母。我本以为可以用 但这显然行不通。如何将字符串的首字母转