Graphiql: JSON object as String in query variables

Created on 27 Dec 2016  路  8Comments  路  Source: graphql/graphiql

Can you please guide on how to pass below JSON object as String

{
"filter": {
"region": "APAC",
"code": {"in": [ "HK1", "SG1" ]},
"account_number": {"nin": [ "1" ]}
}
}

question

Most helpful comment

@asiandrummer's suggestion is a good one. You simply provide a string for your variable which happens to appear as JSON:

{
  "filter": "{ \"region\": \"APAC\", ... }"
}

Within your application, you can first call JSON.parse() on the string variable to get your unstructured JSON object within your server.

All 8 comments

Hey @sudheerj! I'm not really sure what you mean by passing JSON object as String - are you trying to execute a query with above JSON as variables?

Exactly.I want to pass above JSON object as String query variable.It contains many operators and fields.The above expression is a direct Mongoose schema that works on DB.I don't want to pass it as InputObject.

Let me try answering in a couple phases:

  1. I guess the easiest way is, given that the JSON is simple enough (which is probably not what you want), if you declare the type of $filter argument as GraphQLString, you could pass it in as a JSON.stringifyed string from Variable Editor I presume:
{
  "filter": "{ "region: "APAC", ... }"
}

If what you wanted is to pass an object and convert it into a string later, it'll be difficult to achieve that as GraphiQL does not (and probably should not) attempt to process the query/variables strings; instead it merely passes the provided strings to GraphQL executor (in this case graphql-js). You might be able to tweak the fetcher function to detect certain GraphQL variable keys and process into the string format there, but it feels too much of a hack.

  1. I'd advise to create a GraphQLInputObject type for this:
new GraphQLInputObjectType({
  name: 'filter',
  fields: {
    "region": { type: GraphQLString },
    "code": { type: new GraphQLInputObjectType({ ... }) },
    "account_number": { type: new GraphQLInputObjectType({ ... }) },
  }
});

FYI, you may already know this, but I did a quick google search and came up with a couple of example adapter libraries with GraphQL and Mongoose DB (e.g. graffiti-graphql), as well as some posts on what other people did to connect the two.

For the last mark, this question is probably more suited for graphql-js repository (I'm making an educated guess from looking at your other questions and the fact that you may be using graphql-js reference implementation for your application)

I should pass JSON object only because it contains mongoose operators which executed directly.You can observe $gt,$gte,$in,$nin etc so I'am expecting them as String instead on Input object.

Do I need to pass filter args for Root query here? Other inputs will be passed to Model object

let RootQuery = new GraphQLObjectType({
  name: 'Query',      //Return this type of object
  fields: () => ({
    accounts: AccountQueries.accounts

  })
});

@asiandrummer's suggestion is a good one. You simply provide a string for your variable which happens to appear as JSON:

{
  "filter": "{ \"region\": \"APAC\", ... }"
}

Within your application, you can first call JSON.parse() on the string variable to get your unstructured JSON object within your server.

@leebyron the suggestion to escape quotes in a string is very cumbersome for large data and not a reasonable solution for this in my opinion. Given there is a JSONString input type, GraphiQL should support transforming the Object variable to JSONString. Defining custom Input Types is also not possible for my situation since this is for a mutation that needs to support multiple types and interfaces are not supported for input types. My work around for now is to do the hacky modification of my fetcher. This still has the problem of GraphiQL highlighting my variables saying, "Expected value of type JSONString". But I guess I can just ignore this since this is only used by our sys admins.

For anyone else facing this same situation this is my fetcher:

fetcher = (params) => {
    let {variables = {}} = params;
    variables = variables && Object.keys(variables).reduce((result, key) => {
      if (hasIn(variables[key], '__stringify')) {
        return {...result, [key]: JSON.stringify(variables[key].__stringify)};
      }
      return {...result, [key]: variables[key]};
    }, {});
    return fetch('/graph', {
      method: 'POST',
      headers: new Headers({
          'Content-Type': 'application/json'
      }),
      body: JSON.stringify({...params, variables})
    }).then((response) => {
      return response.json();
    });
  }

I used a __stringify wrapper to avoid stringifying unintended objects.

@nikordaris, JSONString is not part of the standard set of scalars and GraphiQL only supports the standard set, that's a custom scalar type added by your server. If you're sending complex unstructured JSON data as a string - I suggest calling JSON.stringify on the client before sending the query

I have the same issue. I can submit the JSON just fine, but graphIQL complains that the type is supposed to be Json.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sashahavia picture sashahavia  路  50Comments

rherrmann picture rherrmann  路  19Comments

wmertens picture wmertens  路  31Comments

asiandrummer picture asiandrummer  路  12Comments

Glavin001 picture Glavin001  路  10Comments