Is it possible to add a json scalar type to avoid having to send raw json as a string? That way in a JS web environment it won't be necessary to JSON.parse the string data.
Yes, you can define custom scalars.
There's an example in the ScalarType docs: http://www.rubydoc.info/github/rmosolgo/graphql-ruby/GraphQL/ScalarType
and one in the spec: https://github.com/rmosolgo/graphql-ruby/blob/master/spec/graphql/scalar_type_spec.rb
How does that look?
@rmosolgo How do you use a custom scalar type as a mutation input field?
JsonType = GraphQL::ScalarType.define do
name "JSON"
coerce_input -> (x) { JSON.parse(x) }
coerce_result -> (x) { JSON.dump(x) }
end
input_field :whatever, JsonType
The above code is causing mutation input to be wrapped in GraphQL::Query::Arguments.
Ohh that sounds like a bug in Query::Arguments -- I think it assumes all ruby hashes are meant to represent InputObjectTypes, but now it's possible that that's not the case!
As a workaround you can call Arguments#to_h to get a plain hash version of that object.
I tried this on an input type argument to be used in a relay mutation, and I keep getting:
Argument '<argument-name>' on InputObject 'SomethingInput' has an invalid value
The way I'm writing the mutation is:
mutation {
createGroupConsultation(input: {something: {argument-name: {other_thing: 2}, other_argument: 1}}) {
result
}
}
Arguments of other types work just fine. Hope this is clear enough, as I'm also trying to figure out want went wrong, but as far as I can tell when getting here, the value.value is #<GraphQL::Language::Nodes::InputObject:0x007fc75ba419b8 @arguments=[], @col=57, @line=2> and field.type is scalar, which makes the validation return false.
In other words, the value is being stored as an InputObject as not as a hash.
I suspect it might be the way I'm passing the objects in, but not sure.
I was able to fix this by sending the arguments as strings.
mutation {
createGroupConsultation(input: {something: {argument-name: "{\"other_thing\": 2}", other_argument: 1}}) {
result
}
}
Is this the intended behaviour?
Is this the intended behaviour?
Yes -- for the JsonType described above, the data must be sent as string. If the data is given as GraphQL arguments, GraphQL will try to validate them!
My arguments are still getting wrapped in GraphQL::Query::Arguments. On the client I am calling JSON.stringify(object) and passing that as a param. What am I doing wrong?
Taking a crack at fixing this here: https://github.com/rmosolgo/graphql-ruby/pull/304
After that, argument :json, JSONScalar will be a plain hash instead of a Query::Arguments
That fix was merged into 0.19.3, please let me know if you find the argument bug again!
Just wanted to add a comment here in case it helps other folks that find their way here. Using SchemaClassName.execute(query_string) to test my schema, I was getting a parse error.
{"errors"=>[{"message"=>"Parse error on \":\" (STRING) at [1, 44]", "locations"=>[{"line"=>1, "column"=>44}]}]} or
{"errors"=>[{"message"=>"Parse error on \"super\" (STRING) at [1, 39]", "locations"=>[{"line"=>1, "column"=>39}]}]}
Don't forget to double escape the JSON string in your query string.
For example:
query_string = <<~QUERY
mutation {
updateForm(
id: #{form.id},
data: "{ \\"super\\": \\"special\\" }"
) { data }
}
QUERY
result = SchemaClassName.execute(query_string)
@rmosolgo - Is supporting non-string encoded custom JSON scalars totally off the table? We've hit a use case where they could be useful. graphql.js supports them via graphql-type-json so it would be consistent with the reference GraphQL implementation :)
I'm open to it!
Most helpful comment
@rmosolgo How do you use a custom scalar type as a mutation input field?
The above code is causing mutation input to be wrapped in
GraphQL::Query::Arguments.