如何将现有的 json 变成 GraphQL 端点?
How can I turn this existing json into a GraphQL endpoint?
我正在创建一个从 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
});
我在您的代码中看到的最大问题是您正在尝试为查询 (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')
这将 return 一个对象,您可以 return 在解析器中为 getBoxscore
查询。
resolve: () => testData
但是我们想要 return 来自 API 调用的数据,所以我们改为这样做:
resolve: () => {
const url = 'http://games.espn.com/ffl/api/v2/boxscore?leagueId=1150587&seasonId=2017&teamId=5&scoringPeriodId=7'
return axios(url)
}
Axios return 是一个 Promise,这很棒,因为我们的解析器可以 return 一个值,或者一个将解析该值的 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 如此强大的部分原因在于能够在字段级别 return 操纵数据的编辑方式。因此,对于任何字段,您都可以在 return 将其 return 发送到客户端之前轻松地操纵由父对象 return 编辑的数据。
一个愚蠢的例子可能是在您的 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
以反映该调用 return 编辑的数据。
有很多值得探索的可能性。祝你好运!
我正在创建一个从 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
});
我在您的代码中看到的最大问题是您正在尝试为查询 (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')
这将 return 一个对象,您可以 return 在解析器中为 getBoxscore
查询。
resolve: () => testData
但是我们想要 return 来自 API 调用的数据,所以我们改为这样做:
resolve: () => {
const url = 'http://games.espn.com/ffl/api/v2/boxscore?leagueId=1150587&seasonId=2017&teamId=5&scoringPeriodId=7'
return axios(url)
}
Axios return 是一个 Promise,这很棒,因为我们的解析器可以 return 一个值,或者一个将解析该值的 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 如此强大的部分原因在于能够在字段级别 return 操纵数据的编辑方式。因此,对于任何字段,您都可以在 return 将其 return 发送到客户端之前轻松地操纵由父对象 return 编辑的数据。
一个愚蠢的例子可能是在您的 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
以反映该调用 return 编辑的数据。
有很多值得探索的可能性。祝你好运!