【问题标题】:How do I make a struct with nested json?如何使用嵌套的 json 创建结构?
【发布时间】:2021-09-13 21:55:08
【问题描述】:

我的 api 有一个 JSON 响应,它返回:

[
    {
        "id": 1,
        "chapter": 5,
        "amount": 28,
        "texts": [
            {
                "lyric": "lorem ipsum",
                "number": 1
            },
            {
                "lyric": "lorem foo bar",
                "number": 2
            }
        ],
        "book": 1
    }
]

我试过了

struct Chapter: Decodable, Identifiable {
    var id: Int
    var chapter: Int
    var amount: Int

    struct Lyrics: Codable {
         var lyricText: String
         var lyricNumber: Int
     }

    enum Codingkeys: String, CodingKey {
        case lyricText = "lyric"
        case lyricNumber = "number"
    }
}

但我在拨打电话时收到以下错误


dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.})))

我的 API 调用如下所示:

...
    @Published var chapters = [Chapter]()
    func fetchBookDetails() {
        if let url = URL(string: url) {
            let session = URLSession(configuration: .default)
            let task = session.dataTask(with: url) { (data, response, error) in
                if error == nil {
                    if let safeData = data {
                        do {
                            
                            let response = try JSONDecoder().decode([Chapter].self, from: safeData)
                            DispatchQueue.main.async {
                                self.chapters = response
                            }
                        } catch {
                            print(error)
                        }
                        
                    }
                }
            }
            task.resume()
        }
    }

我猜这个结构看起来不错,但是 api 调用在抱怨 - 知道它可能是什么吗?还是结构做错了

【问题讨论】:

  • "number": 2 后面的逗号使您的 JSON 无效。您是否完全可以控制 API 的输出?
  • texts 是另一个 struct 的数组
  • @jnpdx 很好 - 在“真实”响应中没有尾随逗号 - 只是我这里的一个错字。
  • @MadProgrammer 那应该是什么样子?
  • 您得到的错误非常清楚——JSON 无效。如果这不是“真实”数据,则应显示 JSON 的真实表示,以便确定问题所在。

标签: swift swift-structs


【解决方案1】:

texts是一个子结构(属性数组),所以需要为它定义第二个容器,例如

struct Text: Codable {
    let lyric: String
    let number: Int
}

然后您可以更新Chapter 以引用类似...的子结构

struct Chapter: Decodable {
    let id: Int
    let chapter: Int
    let amount: Int
    let book: Int
    
    let texts: [Text]
}

最后,加载它...

let chapters = try JSONDecoder().decode([Chapter].self, from: jsonData)

但是错误信息呢?

dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around character 0." UserInfo={NSDebugDescription=Invalid value around character 0.})))

哦,对了,但是错误消息表明您下载的内容有问题。在这些情况下,我喜欢将数据转换为 String 并在可能的情况下打印出来,这样您就知道返回给您的是什么。

例如:

let actualText = String(data: safeData, encoding: .utf8)

打印出来看看你实际得到了什么


Playground 测试代码

import UIKit

let jsonText = """
[
    {
        "id": 1,
        "chapter": 5,
        "amount": 28,
        "texts": [
            {
                "lyric": "lorem ipsum",
                "number": 1
            },
            {
                "lyric": "lorem foo bar",
                "number": 2
            },
        ],
        "book": 1
    }
]
"""

struct Text: Codable {
    let lyric: String
    let number: Int
}

struct Chapter: Decodable {
    let id: Int
    let chapter: Int
    let amount: Int
    let book: Int
    
    let texts: [Text]
}

let jsonData = jsonText.data(using: .utf8)!
do {
    let chapters = try JSONDecoder().decode([Chapter].self, from: jsonData)
} catch let error {
    error
}

【讨论】:

  • 一些小事:1) 使用Data(jsonText.utf8) 转换为数据通常更容易。 2) 在 do-try-catch 中,不需要 let error,因为它会自动“创建”一个要使用的 error 变量。 3) 你应该用print(error) 打印出那个错误。
  • @George 2) 毫无疑问并消除对“那是从哪里来的?”的困惑; 3)这是一个游乐场,所以我直接在右边的栏中打印:P
  • 非常感谢您的帮助,错字出现在我的端点中 - 写的是 bok 而不是 book
猜你喜欢
  • 1970-01-01
  • 2017-12-14
  • 2014-11-24
  • 2022-11-24
  • 1970-01-01
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 2018-05-18
相关资源
最近更新 更多