【问题标题】:GraphQL type with a variable field name具有可变字段名称的 GraphQL 类型
【发布时间】:2023-01-09 15:47:06
【问题描述】:

我正在尝试将 Rest Countries API (restcountries.com) 公开为 GraphQL API。但是,我正在努力找出在 GraphQL 中创建类型定义以显示字段 name.nativeName 的最佳方法。

例如:如果您发送请求以获取有关加拿大等国家/地区的信息 (GET https://restcountries.com/v3.1/alpha/ca),那么我们将收到如下响应:

"name": {
    "common": "Canada",
    "official": "Canada",
    "nativeName": {
        "eng": {
            "official": "Canada",
            "common": "Canada"
        },
        "fra": {
            "official": "Canada",
            "common": "Canada"
        }
    }
}

正如您在上面的响应中看到的那样,nativeName 字段是一个具有两个内部字段 eng 和 fra 的对象。但是,如果我发送请求以获取另一个国家/地区,例如芬兰 (GET https://restcountries.com/v3.1/alpha/fi),响应将如下所示:

"name": {
    "common": "Finland",
    "official": "Republic of Finland",
    "nativeName": {
        "fin": {
            "official": "Suomen tasavalta",
            "common": "Suomi"
        },
        "swe": {
            "official": "Republiken Finland",
            "common": "Finland"
        }
    }
}

但这一次,对于芬兰,nativeName 具有不同的字段 fin 和 swe。换句话说,nativeName 的内部字段会根据我们查询的国家/地区而变化。

那么我如何在我的 GraphQL API 中创建适当的 typeDef 和解析器来支持这种情况,字段名称不可预测?到目前为止,这是我的 typeDef,但我不知道如何为 nativeName 创建类型。

type Query {
    all: [Country!]!
}

type Country {
    name: CountryName!
}

type CountryName {
    common: String!
    official: String!
    nativeName: ... # I have no idea how to map nativeName
}

有没有办法在这个类型变量中创建一个字段名称?任何人都可以建议一种使用nativeName 完成此 typeDef 的方法以及解析器的外观吗?

【问题讨论】:

    标签: node.js typescript graphql


    【解决方案1】:

    这是一个常见问题,您通常可以在“GraphQL 地图”下找到它,例如here。 GraphQL 中不能有动态字段。

    现在您应该问问自己,保持响应的原始形状有多重要。如果您不关心形状,GraphQL 的教条方式就是简单地返回一个列表:

    type NativeName {
      lang: String!
      official: String 
      common: String
    }
    
    type CountryName {
      nativeName: [NativeName!]!
    }
    

    您的响应形状当然会改变。您的解析器可能是:

    resolve(parent) {
      return Object.entries(parent.nativeName).map(([lang, rest]) => ({ lang, ...rest }));
    }
    

    如果您关心结果形状并希望它尽可能接近原始形状,则可以按照大多数问题(如上面的问题)中建议的方式使用 JSON 标量。虽然你失去了打字。

    最后一个完全疯狂的方法是:三位语言代码的数量是有限的。您可以将它们中的每一个添加到一个对象中:

    type NativeName {
      official: String 
      common: String
    }
    
    type NativeNameMap {
      afr: NativeName
      ain: NativeName
      aka: NativeName
      ...
    }
    
    type CountryName {
      nativeName: NativeNameMap
    }
    

    这听起来很疯狂,但如果调用者提前知道返回的语言是什么,它可能是可行的。

    【讨论】:

      猜你喜欢
      • 2021-10-23
      • 2018-06-01
      • 1970-01-01
      • 2020-09-22
      • 1970-01-01
      • 1970-01-01
      • 2016-01-12
      • 2020-09-16
      相关资源
      最近更新 更多