如何将这个现有的 json 转换为 GraphQL 端点?
Posted
技术标签:
【中文标题】如何将这个现有的 json 转换为 GraphQL 端点?【英文标题】:How can I turn this existing json into a GraphQL endpoint? 【发布时间】:2018-04-09 07:58:55 【问题描述】:我正在创建一个从 api 接收数据的应用程序,我需要轻松访问该远程数据。目前,我的游戏计划是在用户需要数据时从端点下载 json 文件,但如果有人可以推荐一种使用远程 url 作为 GraphQL 源的方法,我也会很感激。
关于手头的问题:
我不确定应该如何构建我的 schema.js 文件。这是我尝试使用的实际数据actual data
但这是我整理的粗略大纲。它或多或少概述了我无法访问的所有嵌套字典和列表。如果有人可以为我提供几个示例,说明如何访问这些嵌套的字典、列表和值,我将不胜感激!
boxscore
progames
,
teams
[
slots
,
appliedStats : float,
appliedStats1: float,
team
[
rank: int,
player
,
watch: boolean,
trade: boolean,
currentProjStats
,
proGameIds
],
[
...
],
[
...
],
,
teamId: int,
appliedActive: int,
appliedProjActive: float,
],
[
]
这是我尝试过的一个例子
const
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLSchema,
GraphQLList,
GraphQLNonNull,
GraphQLBoolean,
GraphQLFloat
= require('graphql');
const axios = require('axios');
const PlayerType = new GraphQLObjectType(
name: 'Player',
fields:() => (
droppable: type:GraphQLBoolean,
percentStarted: type:GraphQLFloat,
jersey: type:GraphQLString,
playerRatingSeason: type:GraphQLFloat,
positionRank: type:GraphQLInt,
isIREligible: type:GraphQLBoolean,
draftRank: type:GraphQLInt,
value: type:GraphQLInt,
universeId: type:GraphQLInt,
firstName: type:GraphQLString,
elligibleSlotsCategoryIds: type:elligibleSlotsCategoryIdsType,
gameStarterStatus: type:GraphQLInt,
lastName: type:GraphQLString,
sportsId: type:GraphQLInt,
healthStatus: type:GraphQLInt,
percentOwned: type:GraphQLFloat,
proTeamId: type:GraphQLInt,
tickerId: type:GraphQLInt,
isActive: type:GraphQLBoolean,
playerId: type:GraphQLInt,
percentChange: type:GraphQLFloat,
defaultPositionId: type:GraphQLInt,
totalPoints: type:GraphQLFloat
)
);
const CurrentPeriodProjectedStatsType = new GraphQLObjectType(
name: 'CurrentPeriodProjectedStats',
fields: () => (
appliedProjectedStatTotal: type:GraphQLFloat,
)
);
const ProGameIdsType = new GraphQLObjectType(
name: 'ProGameIds',
fields: () => (
id: type:GraphQLInt,
)
);
const CurrentPeriodRealStatsType = new GraphQLObjectType(
name: 'CurrentPeriodRealStats',
fields: () => (
appliedRealStatTotal: type:GraphQLFloat,
)
);
const SlotsType = new GraphQLObjectType(
name: 'Slots',
fields:() => (
// This might take type:GraphQLList, not sure though //
pvoRank: type: GraphQLInt,
player: type: PlayerType,
watchList: type:GraphQLBoolean,
isKeeper: type:GraphQLBoolean,
isTradeLocked: type:GraphQLBoolean,
currentPeriodProjectedStats: type: CurrentPeriodProjectedStats,
proGameIds: type: ProGameIds,
opponentProTeamId: type:GraphQLInt,
slotCategoryId: type:GraphQLInt,
lockStatus: type:GraphQLInt,
isQueuedWaiverLocked: type:GraphQLBoolean,
currentPeriodRealStats: type:CurrentPeriodRealStatsType
)
);
/*
const ProgamesType = new GraphQLObjectType(
name: 'Progames',
field: () => (
)
);
*/
const TeamsType = new GraphQLObjectType(
name: 'Teams',
fields:
team1: type:GraphQLList,
team2: type:GraphQLList,
);
const BoxscoreType = new GraphQLObjectType(
name: 'Boxscore',
fields: () => (
// progames: type:ProgamesType,
teams: () => GraphQLList(TeamsType),
scoringPeriodId: type:GraphQLInt,
matchupPeriodId: type:GraphQLInt,
homeTeamBonus: type:GraphQLInt
)
);
const MetadataType = new GraphQLObjectType(
name: 'Metadata',
fields: () => (
leagueId: type:GraphQLString,
status: type:GraphQLString,
seasonId: type:GraphQLString
)
);
const EspnQuery = new GraphQLObjectType(
name: 'EspnQueryType',
fields:
boxscore: type:BoxscoreType,
,
resolve(parentValue, args)
);
// Keep at the bottom //
module.exports = new GraphQLSchema(
query: EspnQuery
);
【问题讨论】:
【参考方案1】:我在您的代码中看到的最大问题是您正在尝试为 Query (EspnQuery) 添加解析器。即使它被定义为GraphQLObjectType
,因为它位于根目录,它的解析器永远不会被调用。您要做的是将现有数据结构包装在EspnQuery
的某种字段中:
const BoxscoreDataType = new GraphQLObjectType(
name: 'BoxscoreData',
fields:
boxscore: type:BoxscoreType,
metadata: type:MetadataType,
,
);
const EspnQuery = new GraphQLObjectType(
name: 'EspnQuery',
fields:
getBoxscore:
type: BoxscoreDataType,
resolve: () => // We'll come back to this in a minute
,
,
);
出于测试目的,您可以将示例 JSON 数据放在单独的文件中,只需 require
即可:
const testData = require('./testData.json')
这将返回一个对象,您可以在解析器中为getBoxscore
查询返回该对象。
resolve: () => testData
但我们想从 API 调用中返回数据,所以让我们这样做吧:
resolve: () =>
const url = 'http://games.espn.com/ffl/api/v2/boxscore?leagueId=1150587&seasonId=2017&teamId=5&scoringPeriodId=7'
return axios(url)
Axios 返回一个 Promise,这很棒,因为我们的解析器可以返回一个值,也可以返回一个将解析为该值的 Promise。请确保您不要忘记return
!
奖励:使用参数
您还可以为任何字段定义参数,然后可以在解析器中使用这些参数。所以getBoxscore
可能看起来像这样:
getBoxscore:
type: BoxscoreDataType,
args:
leagueId:
name: 'leagueId',
type: new GraphQLNonNull(GraphQLInt)
,
seasonId:
name: 'seasonId',
type: new GraphQLNonNull(GraphQLInt)
,
teamId:
name: 'teamId',
type: new GraphQLNonNull(GraphQLInt)
,
scoringPeriodId:
name: 'scoringPeriodId',
type: new GraphQLNonNull(GraphQLInt)
resolve: (obj, leagueId, seasonId, teamId, scoringPeriodId ) =>
const url = `http://games.espn.com/ffl/api/v2/boxscore?leagueId=$leageId&seasonId=$seasonId&teamId=$teamId&scoringPeriodId=$scoringPeriodId`
return axios(url)
奖励 2:解析器
此外,不要忘记 GraphQL 如此强大的部分原因在于能够在字段级别操纵数据的返回方式。因此,对于任何字段,您都可以在将父对象返回的数据返回给客户端之前轻松地对其进行操作。
一个愚蠢的例子可能是在你的 PlayerType 中的 firstName 上附加一个解析器:
resolve: ( firstName ) =>
return firstName.toUpperCase()
一个更有趣的用途可能是对不同的 API 端点进行额外的调用。例如,对于 SlotsType 上的 player
字段,您可以像这样附加解析器:
resolve: ( player: playerId ) =>
const url = `some url that uses that $playerId`
return axios(url)
当然,如果您这样做了,您可能还会修改您的 PlayerType
以反映该调用返回的数据。
有很多值得探索的可能性。祝你好运!
【讨论】:
谢谢!太棒了!我遇到了另一个问题,但这很可能是由于我的 graphql noob-ness。我可以给你发消息寻求帮助吗? 在接下来的 6 个小时里,我会断断续续。请随时联系我:chat.***.com/rooms/157840/graphql以上是关于如何将这个现有的 json 转换为 GraphQL 端点?的主要内容,如果未能解决你的问题,请参考以下文章
如何将 Excel 转换为 JSON 并将其附加到现有的 JSON 文件?
如何将数据的 JSON 格式转换为 GraphQL 查询格式
如何将现有的 dynamo db 与 AWS Amplify 和 graphql 一起使用