2

我正在使用协议来编码符合的结构:

protocol RequestParameters: Encodable {

}

extension RequestParameters {

    func dataEncoding() -> Data? {
        guard let data = try? JSONEncoder().encode(self) else { return nil }
        return data
    }
}

这对于编码这些类型的结构非常有效:

struct StoreRequest: RequestParameters {

    var storeCode : String

    var storeNumber : String    
}

但是,有时我的请求需要一些“共享”参数:

struct SpecialStoreRequest: RequestParameters {

    var storeCode : String

    var storeNumber : String  

    // Shared Parameters that appear in 70% of my requests
    var sharedParam1 : String?
    var sharedParam2 : String?
    var sharedParam3 : String?
    var sharedParam4 : String?
    var sharedParam5 : String?
}

我可以简单地将这些共享参数写在需要它们的每个请求结构上,但我想知道是否可以将它们分组到另一个结构中并以某种方式修改编码以在顶层对它们进行编码?

我正在考虑类似的事情:

struct SharedParameters {

    // Shared Parameters that appear in 70% of my requests
    var sharedParam1: String?
    var sharedParam2: String?
    var sharedParam3: String?
    var sharedParam4: String?
    var sharedParam5: String?

    enum CodingKeys: String, CodingKey {
        case sharedParam1
        case sharedParam2
        case sharedParam3
        case sharedParam4
        case sharedParam5
    }
}

struct SpecialStoreRequest: RequestParameters {

    var storeCode : String

    var storeNumber : String  

    var sharedParams : SharedParameters?
}

最后一个结构的问题是生成的编码与第一个不同,因为我的共享参数将在“ sharedParams ”键内编码:

{
   "storeCode" : "ABC",
   "storeNumber" : "123456",
   "sharedParams" : {"sharedParam1" : "A","sharedParam2" : "B", ...}
}

但是我需要将它们与我的其他现有参数(在本例中为 storeCode 和 storeNumber)一起编码。

{
   "storeCode" : "ABC",
   "storeNumber" : "123456",
   "sharedParam1" : "A",
   "sharedParam2" : "B", 
   ...
}

编辑: 为了使问题更清楚,假设有可能,这里应该怎么做才能使这个结构直接在其父级上由键值编码?

extension SharedParameters: Encodable {

    func encode(to encoder: Encoder) throws {

        // What goes here? (Is it even possible?)

    }
}
4

1 回答 1

0

想知道是否可以将它们分组到另一个结构中并以某种方式修改编码以在顶层对它们进行编码?

您无法更改电流Encoder及其行为方式,但是,

您可以通过自定义Encode功能来实现,

制作两个容器并使用共享参数CodingKeys进行编码

变量中的参数sharedParameters

观察下面的代码。

    struct Others: Codable {
    var sharedParam1: String
    var sharedParam2: String

    enum CodingKeys: String, CodingKey {
        case sharedParam1
        case sharedParam2
    }
}



  struct MyCustomReq: Codable {
    var p1: String

    var p2: String

    var shared: Others

    enum CodingKeys: String, CodingKey {
        case p1
        case p2
        case shared
    }
}

    extension MyCustomReq {
        func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(p1, forKey: .p1)
            try container.encode(p2, forKey: .p2)
            //Others = sharedParams container. with its CodingKeys
            var container2 = encoder.container(keyedBy: Others.CodingKeys.self)
            try container2.encode(shared.sharedParam1, forKey: .sharedParam1 )
            try container2.encode(shared.sharedParam1, forKey: .sharedParam2)
        }
    }

使用测试

var oth = Others(sharedParam1: "Shared1", sharedParam2: "Shared2")
var object = MyCustomReq.init(p1: "P1", p2: "P2", shared: oth)

let encoder = JSONEncoder()
let data = try encoder.encode(object)

print(String(data: data, encoding: .utf8)!)

输出

{ "p2":"P2",

"sharedParam1":"Shared1",

"p1":"P1",

"sharedParam2":"Shared1"

}

现在让我们进入下一步,

创建一个类并Encoder在那里自定义共享的,然后调用它的函数。

观察最终结果。

final class MyParamsEncoded: Codable {
var sharedParams: Others
init (sharedParam: Others) {
    self.sharedParams = sharedParam
}
func encode(to encoder: Encoder) throws {
    var container2 = encoder.container(keyedBy: Others.CodingKeys.self)
    try container2.encode(sharedParams.sharedParam1, forKey: .sharedParam1 )
    try container2.encode(sharedParams.sharedParam1, forKey: .sharedParam2)
}
}

现在添加这个类之后,你可以像这样使用它,它会给你同样的结果。

extension MyCustomReq {
func encode(to encoder: Encoder) throws {
    var container = encoder.container(keyedBy: CodingKeys.self)
    try container.encode(p1, forKey: .p1)
    try container.encode(p2, forKey: .p2)
    //Using the class wrapping, final Result of using 
    var cont = try MyParamsEncoded(sharedParam: shared).encode(to: encoder)

}
}
于 2018-11-06T09:31:14.213 回答