最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - GraphQL: build query arguments from object - Stack Overflow

programmeradmin2浏览0评论

If I have an object:

{"where":{"publishedAt_lt":"2018-01-01"}}

How can I convert it to a string suitable for query arguments?

articles(where: {publishedAt_lt: "2018-01-01"})

If I have an object:

{"where":{"publishedAt_lt":"2018-01-01"}}

How can I convert it to a string suitable for query arguments?

articles(where: {publishedAt_lt: "2018-01-01"})
Share Improve this question asked Jun 2, 2018 at 18:41 TerionTerion 2,5064 gold badges30 silver badges43 bronze badges 3
  • 1 That's exactly what you already have? The quotes around a key (in this instance) are meaningless. – jhpratt Commented Jun 2, 2018 at 18:46
  • This is an example. I have a simple JS object, that is coming from outside and I need to convert it to gql argument – Terion Commented Jun 2, 2018 at 19:02
  • can you post your full query – Ashh Commented Jun 3, 2018 at 8:41
Add a comment  | 

4 Answers 4

Reset to default 13

This looks like an interesting library, I would suggest checking it out:

https://www.npmjs.com/package/json-to-graphql-query

But basically all we need to do is to convert the object to a string while ensuring the keys do not adopt double quotes and integers are not converted into strings, as that might not play well with the graphql schemas we're working with.

Since JSON.stringify() won't accomplish this, I came up with this little function to help with interpolating arguments into my queries:

/**
 * Queryfy.
 *
 * Prep javascript objects for interpolation within graphql queries.
 *
 * @param {mixed} obj
 * @return template string.
 */
const queryfy = obj => {

  // Make sure we don't alter integers.
  if( typeof obj === 'number' ) {
    return obj;
  }

  // Stringify everything other than objects.
  if( typeof obj !== 'object' || Array.isArray( obj ) ) {
    return JSON.stringify( obj );
  }

  // Iterate through object keys to convert into a string
  // to be interpolated into the query.
  let props = Object.keys( obj ).map( key =>
    `${key}:${queryfy( obj[key] )}`
  ).join( ',' );

  return `{${props}}`;

}

Here is a reduced portion of my code where I am using this successfully:

const dateQuery = {};

if( !! date1 ) {

  dateQuery.after = {
    year: parseInt( date1.format( 'YYYY' ) ),
    month: parseInt( date1.format( 'M' ) ),
    day: date1.format( 'D' ) - 1,
  }

}
if( !! date2 ) {

  dateQuery.before = {
    year: parseInt( date2.format( 'YYYY' ) ),
    month: parseInt( date2.format( 'M' ) ),
    day: date2.format( 'D' ) - 1,
  }

}

const query = await client.query( {
  query: gql `{
    apiResponses( where: {
      dateQuery: ${queryfy( dateQuery )}
    } ) {
      edges {
        node {
          apiResponseId
          title
          date
          json
        }
      }
    }
  }`
} );

That being said, I am going to check out the library mentioned and probably use that moving forward.

I took KMcAloon approach and made it also support array. That way you can fully make your query as an object and in the last step wrap it => for example

mutation createPackage {
  createPackage(
    data: ${queryfy(data)}
  ) {
    name
    _id
  })
}

/**
 * Queryfy.
 *
 * Prep javascript objects for interpolation within graphql queries.
 *
 * @param {mixed} obj
 * @return template string.
 */
const queryfy = obj => {
  // Make sure we don't alter integers.
  if (typeof obj === 'number') {
    return obj;
  }

  if (Array.isArray(obj)) {
    const props = obj.map(value => `${queryfy(value)}`).join(',');
    return `[${props}]`;
  }

  if (typeof obj === 'object') {
    const props = Object.keys(obj)
      .map(key => `${key}:${queryfy(obj[key])}`)
      .join(',');
    return `{${props}}`;
  }

  return JSON.stringify(obj);
};

this is not answering your question but your question should usually not come up if you follow best practices: GraphQL queries should be static - that means you don't generate them from a variable input. Maybe you have a valid use case for this but I can hardly imagine any. Please let me know in the comments.

When your client has a variable input for a field argument you want to use variables instead:

query getArticles($filter: ArticlesFilter) { # Please insert your input type name
  articles(where: $filter) {
    # ...
  }
}

You can then pass in this input in the variables field of the query:

let givenObject = {"where":{"publishedAt_lt":"2018-01-01"}}; // said object
fetch('/graphql', {
  method: 'POST',
  body: JSON.stringify({
    query, // put the query string from above
    variables: {
      filter: givenObject,
    },
  }),
});

This is now plain JS, please refer to your client side library. I am sure they have a docs section about that. For react-apollo you can find the docs how to pass variables here.

Try this:

const { where } = {"where":{"publishedAt_lt":"2018-01-01"}}
articleList = articles({where}) // assume articles takes an object - equivalent to articles({where: where}) or articles({where: {publishedAt_lt: "2018-01-01"}}
发布评论

评论列表(0)

  1. 暂无评论