swift - Generic Decodable 停止使用 swift 4.1

标签 swift generics codable decodable jsondecoder

因此我们的 API 中有两种类型的 JSON 响应:

{
  "data": { } // some object in here
  "meta": { } // an object in here
}

{
  "data": [ ] // array of objects
  "meta": { } // an object in here
}

为了解码它们,我们使用 JSONDecoder() 和以下通用响应结构:

public struct Response<T: Codable>: Codable {
    public let data: T
    public let meta: Meta?
}

这在使用 .map(Response<[MyObject]>.self) 的 Swift 4.0 中运行良好或 .map(Response<MySingleObject>.self)

但由于某些原因,这不再适用于 Swift 4.1 和 Xcode 9.3。看起来它根本不映射“数据”,因此认为 [MyObject] 的列表在第一层。

dataCorrupted: Swift.DecodingError.Context
      ▿ codingPath: 3 elements
        - CodingKeys(stringValue: "data", intValue: nil)
        ▿ _JSONKey(stringValue: "Index 0", intValue: 0)
          - stringValue: "Index 0"
          ▿ intValue: Optional(0)
            - some: 0
        - CodingKeys(stringValue: "creationDate", intValue: nil)
      - debugDescription: "Date string does not match format expected by formatter."

请注意,“creationDate”是 MyObject 的一个属性.日期格式绝对正确(在解码器中设置为 .formatted(customFormatter)),因为它适用于 Xcode 9.2 中的 Swift 4.0

我们如何才能在 Swift 4.1 中保持相同的行为?这里的目标是不创建类型 Response为每个 API 响应键入但使用泛型代替,因为唯一的区别是响应对象类型,有时它返回一个列表,有时返回一个 data 下的单个对象。 .

也相关:如果我们使用 Response<[MyObject]>.self 有没有办法强制执行?那也是MyObject必须符合 Codable

提前致谢。

编辑:

下面的代码在 Xcode 9.2 和 Swift 4 中正确映射,但在 Xcode 9.3 和 Swift 4.1 中不映射(创建 nil)

public struct MyObject: Codable {
    public let creationDate: Date

    enum CodingKeys: String, CodingKey {
        case creationDate = "creation_date"
    }
}


public struct Response<T: Codable>: Codable {
    public let data: T
    public let meta: Meta?
}


public struct Meta: Codable {
    public let count: Int?
}


let formatter = DateFormatter()
formatter.dateFormat = "yyyy-mm-dd HH:mm:ss"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)

let jsonDataSingle: Data = """
    {
        "data": { "creation_date": "2018-04-29 18:00:11" },
        "meta": null
    }
""".data(using: .utf8)!

let jsonDataList: Data = """
    {
        "data": [{ "creation_date": "2018-04-10 17:00:11" }, { "creation_date": "2018-04-29 18:00:11" }],
        "meta": null
    }
""".data(using: .utf8)!

let singleObject = try? decoder.decode(Response<MyObject>.self, from: jsonDataSingle)
dump(singleObject)
let listOfObjects = try? decoder.decode(Response<[MyObject]>.self, from: jsonDataList)
dump(listOfObjects)

最佳答案

我没有收到任何错误。请张贴。作为练习,我添加了 CustomStringConvertible 一致性并将转储替换为打印。

extension Response: CustomStringConvertible {
  public var description: String {
    return "data = \(data) | meta = \(meta)"
  }
}

extension MyObject: CustomStringConvertible {
  public var description: String {
    return "date = \(creationDate)"
  }
}

我正在使用通过 App Store 发布的 Xcode 9.3、Swift 4.1 版本 9E145。

enter image description here

关于swift - Generic Decodable 停止使用 swift 4.1,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50089495/

相关文章:

ios - SWIFT:在 UIImage 下绘制 UILabel

Swift macOS Process.run() 端口泄漏

ios - 更正可编码结构 Swift 4 和 KeyNotFound 错误

json - 如果我不确定 key ,我应该如何使用 JSONDecoder 解码 json 对象

iOS 11 UISearchBar 背景颜色

ios - bash ./Submodules/OTRKit/scripts/build-all.sh 配置 : error: C compiler cannot create executables

ios - Swift 泛型和向上转型

c# - List<T> 是否在 foreach 的 C# 中创建垃圾

performance - 如何让我的 Rust 函数更通用和高效?

json - 如何使用 swift 4.1 codable(json 解码)过滤无效数据