繁体   English   中英

GraphQL (Apollo) 如何在参数中传递数据结构?

[英]GraphQL (Apollo) how to pass datastructure in parameter?

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

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

谢谢

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

更安全的方法是创建一个包含键和值的类型。 然后,您的字典将是键和值的列表。 而不是访问属性为let value = dictionary[key] ,然后您需要使用let entry = dictionary.find((entry) => entry.key === key); let value = entry && entry.value 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 对数据格式的保证。

斯威夫特 5.1,阿波罗 0.21.0

字典中的键和值需要遵守 Apollo JSONEncodable 协议:

public protocol JSONEncodable: GraphQLInputValue {
  var jsonValue: JSONValue { get }
}

您需要遍历您的 Dictionary 并使用 .jsonValue(JSONEncodable 协议)返回每个对象。

[字符串:任何?] vs [字符串:字符串]

如果您将 [String : String] 的字典传递给 Apollo,它会自动工作,因为 String 符合 JSONEncodable 协议。 键和值都是字符串类型。

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

        }

    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM