Swift 5.1、Apollo 0.21.0
字典中的键和值需要遵守 Apollo JSONEncodable 协议:
public protocol JSONEncodable: GraphQLInputValue {
var jsonValue: JSONValue { get }
}
您需要遍历您的字典并使用 .jsonValue(JSONEncodable 协议)返回每个对象。
[String : Any?] vs [String : String]
如果您将 [String : String] 的字典传递给 Apollo,它将自动工作,因为 String 符合 JSONEncodable 协议。 key 和 value 都是 String 类型。
JSON 在 Swift 中通常表示为 [String : Any?],这意味着键必须是 String,但值可以是 Any 对象(Array、Bool、Double、Null、String、Dictionary)。
因为 Apollo 不知道 Any 对象是什么,它会导致 SIGABRT。这是因为该值可能是您编写的与 JSON 不兼容的自定义类。
您必须将 Any 对象强制转换为符合 JSONEncodable 协议的类。
由于 [String : Any?] 默认情况下无法定义 Any 对象,因此通用 JSON 库通过创建一个新类来表示 JSON 数据来做到这一点。
下面的示例将 JSONEncodable 协议扩展为 GenericJSON 类,以确保该值符合 Apollo 突变所需的 JSONEncodable 协议。
构建符合 JSONEncodable 协议的字典
- 将通用 JSON 库添加到您的 pod 文件中:
https://github.com/zoul/generic-json-swift
pod 'GenericJSON'
- 导入 GenericJSON 库并在一些 ApolloExtensions.swift 文件中为您的 自定义 JSON GraphQL 标量 创建一个别名。此别名将映射到 GenericJSON 库:
import GenericJSON
// CUSTOM JSON SCALAR
public typealias MyJsonScalar = JSON
- 在 ApolloExtensions.swift 文件中,为 GenericJSON JSON 添加 JSONEncodable 扩展:
extension JSON: JSONEncodable {
public var jsonValue: JSONValue {
if self.objectValue != nil {
return jsonObject as JSONObject
}
if self.arrayValue != nil {
var array : Array<JSONEncodable> = []
for obj in self.arrayValue! {
if obj.arrayValue != nil {
array.append(obj.jsonValue as! Array<JSONEncodable>)
} else if obj.objectValue != nil {
array.append(obj.jsonValue as! JSONObject)
} else {
array.append(obj.jsonValue as! JSONEncodable)
}
}
return array as Array<JSONEncodable>
}
if self.stringValue != nil {
return self.stringValue! as String
}
if self.doubleValue != nil {
return self.doubleValue! as Double
}
if self.boolValue != nil {
return self.boolValue! as Bool
}
if self.isNull {
return "" as String
}
return "" as String
}
public var jsonObject: JSONObject {
var jsonObject : JSONObject = JSONObject(minimumCapacity: self.objectValue!.count)
for (key, value) in self.objectValue! {
if value.arrayValue != nil {
jsonObject[key] = value.jsonValue as! Array<JSONEncodable>
} else if value.objectValue != nil {
jsonObject[key] = value.jsonValue as! JSONObject
} else {
jsonObject[key] = value.jsonValue as! JSONEncodable
}
}
return jsonObject
}
}
- 从您的字典中创建一个 JSON 对象并将其传递到您的 GraphQL 突变中:
func createJSONDictionary() {
let myDictionary : [String: Any?] = ["foo" : "foo", "bar" : 2]
do {
let jsonData : Data = try JSONSerialization.data(withJSONObject: myDictionary, options: [])
if let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String : Any?] {
let json: JSON = try JSON(jsonObject)
self.myGraphQLMutation(json: json)
} else {
// casting error
}
} catch {
// json error
}
}
func myGraphQLMutation(json: JSON) {
// apollo
let apollo : ApolloClient = ApolloHelper.shared.client
// myMutation
let myMutation = MyMutation(json: json)
// perform
apollo.perform(mutation: myMutation, queue: DispatchQueue.global()) { result in
switch result {
case .success(let graphQLResult):
// Deal with GraphQLResult and its data and/or errors properties here
break
case .failure(let error):
// deal with network errors here
return
}
}
}