使用通用数组属性解码结构

时间:2019-06-12 07:13:36

标签: swift generics decodable

我有以下带有泛型的结构,用于分页的API响应:

    static byte FloorLog2(UInt16 value)
    {
        for (byte i = 0; i < 15; ++i)
        {
            if ((value >>= 1) < 1)
            {
                return i;
            }
        }
        return 15;
    }

我希望能够像这样解码它:

struct Paginable<Body> {
    let data: [Body]
    let meta: Meta
}

extension Paginable {
    struct Meta: Codable {
        let pagination: Pagination

        struct Pagination: Codable {
            let total: Int
            let count: Int
            let perPage: Int
            let currentPage: Int
            let totalPages: Int
        }
    }
}

因此,我尝试将其设为let response = try? response.decode(to: Paginable<Segment>.self)

Decodable

这给了我两个错误:

  1.   

    无法将'Paginable.Meta'类型的值转换为预期的参数类型'Paginable <_>。Meta'

extension Paginable where Body == Data { func decode<BodyType: Decodable>(to type: BodyType.Type) throws -> Paginable<BodyType> { guard let decodedJSON = try? JSONDecoder().decode(BodyType.self, from: data) else { throw APIError.decodingFailure } return Paginable<BodyType>(data: decodedJSON, meta: self.meta) } } 语句相同

如果我将meta属性更改为某些基本类型(如Int),则错误消失。但是Meta本身就是return,所以这里有什么问题?

  1.   

    无法将类型“ [Data]”的值转换为预期的参数类型“ Data”

Codable语句相同

如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

您需要像这样使PaginableCodable相符,

struct Paginable<Body>: Codable where Body: Codable {
    let data: [Body]
    let meta: Meta
}

decode(data:to:)中的extension Paginable方法更改为

extension Paginable {
    static func decode<BodyType: Decodable>(data: Data, to type: BodyType.Type) throws -> BodyType? {
        do {
            let response = try JSONDecoder().decode(BodyType.self, from: data)
            return response
        } catch {
            throw error
        }
    }
}

用法:

if let data = str.data(using: .utf8) {
    do {
        let response = try Paginable<Segment>.decode(data: data, to: Paginable<Segment>.self)
        print(response)
    } catch {
        print(error)
    }
}

编辑:

JSON格式:

{
  "data": [
      {
        "name": "Name-1"
      },
      {
        "name": "Name-2"
      }
    ],
    "meta": {
      "pagination": {
        "total": 100,
        "count": 10,
        "perPage": 5,
        "currentPage": 1,
        "totalPages": 10
      }
    }
}