【问题标题】:GraphQL (Apollo) how to pass datastructure in parameter?GraphQL(Apollo)如何在参数中传递数据结构?
【发布时间】:2018-08-02 14:15:01
【问题描述】:

我想用很多输入参数进行查询:

 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 的文档说我必须创建一个输入对象。但是这里我使用的是 apollo 的 js,所以如何在查询中传递一个字典以便不输入所有数据(这里是 3,但可以是 10 到 20)。我想要一种带有输入类型字段的更简洁的方法,但我找不到一个示例。

谢谢

【问题讨论】:

    标签: javascript graphql apollo


    【解决方案1】:

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

    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
    
            }
    
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      在我看来,您可以采取两种方法。

      更安全的方法是创建一个包含键和值的类型。然后,您的字典将是键和值的列表。然后您需要使用let entry = dictionary.find((entry) =&gt; entry.key === key); let value = entry &amp;&amp; entry.value,而不是以let value = dictionary[key] 访问属性。

      // 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 对数据格式所做的保证。

      【讨论】:

        猜你喜欢
        • 2016-12-12
        • 2021-06-09
        • 2021-06-07
        • 1970-01-01
        • 2020-05-21
        • 1970-01-01
        • 2021-12-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多