我想使用大量输入参数进行查询:
apollo_client.mutate({mutation: gql
`mutation mutation($title: String!, $caption: String!, $id: Int!){
mutatePmaHome(pmaData: {id:$id, title: $title, caption: $caption}) {
pma{
title
caption
}
}
}`,
variables: {
title: this.state.title,
caption: this.state.caption,
id: this.state.id
},
}).then(console.log);
当我传递简单数据结构时,这是查询我的查询(Int,String) 但我的问题是:如何在变异查询中传递字典或对象。我不知道如何输入它。
来自graphQL的doc说我必须创建一个输入对象。但是我在这里与apollo在js上,所以如何在我的查询中传递一个字典以便不输入所有数据(这里是3,但它可以是10到20)。我想要一个带有输入类型字段的清洁方法,但我找不到一个例子。
由于
答案 0 :(得分:1)
Swift 5.1,Apollo 0.21.0
字典中的键和值需要遵循Apollo JSONEncodable协议:
public protocol JSONEncodable: GraphQLInputValue {
var jsonValue: JSONValue { get }
}
您需要遍历字典并使用.jsonValue(JSONEncodable协议)返回每个对象。
[String:任意?]与[String:String]
如果您将[String:String]的字典传递到Apollo中,它将自动运行,因为String符合JSONEncodable协议。键和值均为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协议的字典
https://github.com/zoul/generic-json-swift
pod 'GenericJSON'
import GenericJSON
// CUSTOM JSON SCALAR
public typealias MyJsonScalar = JSON
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
}
}
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
}
}
}
答案 1 :(得分:0)
我看到它的方式,你可以采取两种方法。
更安全的方法是创建一个包含键和值的类型。然后,您的字典将是键和值的列表。您需要使用let value = dictionary[key]
。
let entry = dictionary.find((entry) => entry.key === key); let value = entry && entry.value
访问属性
// Before
{
red: 1,
blue: 2,
green: 3,
}
// After
[
{key: 'red', value: 1},
{key: 'blue', value: 2},
{key: 'green', value: 3},
]
类型定义:
type IntegerProperty {
key: ID!
value: Int
}
type IntegerDictionary {
values: [IntegerProperty!]!
}
更快但更少类型安全的方法是使用graphql-type-json
或graphql-json-object-type
之类的内容。这些允许您在GraphQL查询中包含任意JSON;但是,您将失去GraphQL对数据格式的保证。