ios - `convertFromSnakeCase` 策略不适用于 Swift 中的自定义 `CodingKeys`

标签 ios swift codable jsondecoder

我尝试使用 Swift 4.1 的新功能在 JSON 解码期间将 snake-case 转换为 camelCase。

这是 example :

struct StudentInfo: Decodable {
    internal let studentID: String
    internal let name: String
    internal let testScore: String

    private enum CodingKeys: String, CodingKey {
        case studentID = "student_id"
        case name
        case testScore
    }
}

let jsonString = """
{"student_id":"123","name":"Apple Bay Street","test_score":"94608"}
"""

do {
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let decoded = try decoder.decode(StudentInfo.self, from: Data(jsonString.utf8))
    print(decoded)
} catch {
    print(error)
}

我需要提供自定义 CodingKeys,因为 convertFromSnakeCase 策略无法推断首字母缩写词或缩写词(例如 studentID)的大写,但我希望convertFromSnakeCase 策略仍然适用于 testScore。但是,解码器会抛出错误(“没有与键 CodingKeys 关联的值”),而且我似乎无法同时使用 convertFromSnakeCase 策略和自定义 CodingKeys。我错过了什么吗?

最佳答案

JSONDecoder(和 JSONEncoder)的关键策略适用于有效载荷中的所有键——包括您为其提供自定义编码键的键。解码时,JSON key 将首先使用给定的 key 策略进行映射,然后解码器将引用要解码的给定类型的 CodingKeys

在您的情况下,您的 JSON 中的 student_id 键将通过 .convertFromSnakeCase 映射到 studentId。转换的确切算法是 given in the documentation :

  1. Capitalize each word that follows an underscore.

  2. Remove all underscores that aren't at the very start or end of the string.

  3. Combine the words into a single string.

The following examples show the result of applying this strategy:

fee_fi_fo_fum

    Converts to: feeFiFoFum

feeFiFoFum

    Converts to: feeFiFoFum

base_uri

    Converts to: baseUri

因此,您需要更新您的 CodingKeys 以匹配此内容:

internal struct StudentInfo: Decodable, Equatable {
  internal let studentID: String
  internal let name: String
  internal let testScore: String

  private enum CodingKeys: String, CodingKey {
    case studentID = "studentId"
    case name
    case testScore
  }
}

关于ios - `convertFromSnakeCase` 策略不适用于 Swift 中的自定义 `CodingKeys`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49881621/

相关文章:

ios - Xcode + Swift - 如果设备使用的是 iOS 8,则只有某些元素

json - 如何通过 Swift 4 的 Decodable 协议(protocol)使用自定义键?

ios - 如何使用动态元素创建自定义 map View 图钉?

ios - 检测 UIImagePicker OverlayView 方向

ios - 为什么我的 for 循环不正确地增加 strokeColor

swift - 如果用户已经评级,则禁用从用户处获取应用程序评论

ios - 如何发送多行 Apple 推送通知,即 '\n' 字符?

ios - UITabBarController 在 Storyboard的上方添加新的 UIViewController (Swift)

json - 解析具有可解码问题的 JSON

swift - 当我不知道类型时,如何使用类继承进行解码?