【问题标题】:Nesting JSON Dictionary Inside a Key?在键中嵌套 JSON 字典?
【发布时间】:2019-08-15 00:58:56
【问题描述】:

我需要在密钥中发送一个请求,期望它看起来像这样:

 {
  "user": {
    "email": String,
    "password": String
  }
}

我正在尝试通过创建具有电子邮件和密码属性并符合可编码的UserSignupRequest 来做到这一点:

struct UserSignupRequest: Codable {
    let email: String
    let password: String

    enum CodingKeys: String, CodingKey {
        case email
        case password
    }
}

然后通过以下方式为 alamofire 创建参数:

case .signup(let request):
        return ["user": request]
}

我的逻辑是这将在用户父键中创建子键值对,但是我的应用程序在尝试时出现致命错误:

urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])

我确定解决方案很简单,但我无法让它发挥作用!非常感谢

【问题讨论】:

  • 你能把剩下的开关贴出来吗?看起来问题可能出在那个case语句上,但很难说。
  • 没有其他内容可以发布,案例是注册,目前是唯一的案例,我已将其调试到 100% 编码而不是开关的地步
  • 好的。凉爽的。因此,当您在调试器中打印参数时,您会看到您期望看到的内容吗?

标签: ios json swift alamofire codable


【解决方案1】:

JSON序列化

JSONSerialization 仅适用于简单类型,如数组、字典、字符串、数字等。

如果你想使用它,那么你不需要Codable,而是需要函数func toDict() -> [String: Any],它将你的UserSignupRequest 转换为字典。
然后您的开关将如下所示:

case .signup(let request):
    return ["user": request.toDict()]
}

JSON编码器

JSONSerialization 是旧 api,如果您打算使用 Codable,您需要使用:

urlRequest.httpBody = try JSONEncoder().encode(parameters)

无法推断通用参数“T”

我假设你得到的参数如下:

func parameters(for request: RequestType) -> [String: Any] {
    switch request {
    case .signup(let request):
        return ["user": request]
    }
}

所以当你在编码器中传递你的参数时,他不知道要编码什么类型。

要解决,我们不仅可以返回字典,还可以返回特定的协议/类型:

protocol Request {
    func encode(by encoder: JSONEncoder) throws -> Data
}
extension Request where Self: Encodable {
    func encode(by encoder: JSONEncoder) throws -> Data {
        /// since it will be method on specific type, JSONEncoder will know what type is encoding
        return try encoder.encode(self) 
    }
}

struct UserSignupRequest: Codable, Request {
    struct RequestData: Codable {
        let email: String
        let password: String
    }
    let data: RequestData

    enum CodingKeys: String, CodingKey {
        case data = "user"
    }
}

func parameters(for request: RequestType) -> Request {
    switch request {
    case .signup(let requestData):
        return UserSignupRequest(data: requestData)
    }
}

所以现在你可以做

urlRequest.httpBody = try parameters.encode(by: JSONEncoder())

【讨论】:

  • 抛出Generic parameter 'T' could not be inferred
  • 谢谢,您使用的是Request Type,但它从未定义过?
  • @jwarris91 RequestType 它是case signup(request) 的枚举。我不知道你是怎么给这个类型命名的,所以就用了这个名字
  • 啊,太不适应我的情况了,如果成功了,请标记这个答案,非常感谢,对我有意义
猜你喜欢
  • 2018-05-31
  • 1970-01-01
  • 1970-01-01
  • 2014-03-30
  • 2021-05-10
  • 1970-01-01
  • 1970-01-01
  • 2011-12-02
  • 1970-01-01
相关资源
最近更新 更多