如何将现有的 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 编辑的数据。

有很多值得探索的可能性。祝你好运!