如何将现有的json转换为GraphQL端点?

时间:2017-10-27 16:30:30

标签: json node.js express graphql graphql-js

我正在创建一个从api接收数据的应用程序,我需要轻松访问该远程数据。目前,我的游戏计划是在用户需要数据时从端点下载json文件,但如果有人可以推荐使用远程URL作为GraphQL源的方法,我也很感激。

关于手头的问题:

我不确定如何构建schema.js文件。以下是我尝试使用的实际数据actual data

但这是一个粗略的轮廓,我把它放在一起。它或多或少地概述了我访问时遇到的所有嵌套字典和列表。如果有人可以提供一些如何获得这些嵌套的dicts,列表和值的示例,我将非常感激!

{
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 个答案:

答案 0 :(得分: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以反映该通话返回的数据。

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