GraphQL(Apollo)如何在参数中传递datastructure?

时间:2018-02-22 16:21:03

标签: javascript graphql apollo

我想使用大量输入参数进行查询:

 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)。我想要一个带有输入类型字段的清洁方法,但我找不到一个例子。

由于

2 个答案:

答案 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协议的字典

  1. 将通用JSON库添加到您的pod文件中:

https://github.com/zoul/generic-json-swift

pod 'GenericJSON'

  1. 导入 GenericJSON 库,并在某些 ApolloExtensions.swift 文件中为您的自定义JSON GraphQL标量创建别名。该别名将映射到GenericJSON库:
import GenericJSON

// CUSTOM JSON SCALAR

public typealias MyJsonScalar = JSON
  1. 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

    }

}
  1. 从您的字典中创建一个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

        }

    }

}

答案 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-jsongraphql-json-object-type之类的内容。这些允许您在GraphQL查询中包含任意JSON;但是,您将失去GraphQL对数据格式的保证。