Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Discussion] Get arguments as plain objects. #527

Closed
SebastianStehle opened this issue Jan 15, 2018 · 9 comments
Closed

[Discussion] Get arguments as plain objects. #527

SebastianStehle opened this issue Jan 15, 2018 · 9 comments

Comments

@SebastianStehle
Copy link

Hi,

I want to extend my REST with a second endpoint using GraphQL. Some of my inputs are highly dynamic. Therefore I just use JObject class. Can I get the raw arguments in my mutations?

@SebastianStehle SebastianStehle changed the title Get arguments as plain objects. [Discussion] Get arguments as plain objects. Jan 16, 2018
@SebastianStehle
Copy link
Author

SebastianStehle commented Jan 16, 2018

I tried to understand the code, but I don't get it yet. For me it seems, that the input is converted in this way JObject => Dictionary => AST Nodes => Objects

seems to be very complicated, especially because JObject is more powerful and faster than the custom conversion and deserialization stuff. It also generates a lot of allocations right now.

My idea would be to convert everything to JObject instead and get rid of a lot of code.

@joemcbride
Copy link
Member

AST Nodes is for the Query itself, not arguments/variables. You can access the Arguments (as a Dictionary) via the ResolveFieldContext.Arguments. Granted this could potentially be faster, though there are rules in the GraphQL spec in regards to the Arguments which preclude just providing the raw JSON arguments.

@SebastianStehle
Copy link
Author

SebastianStehle commented Jan 16, 2018

The point is: I don't want to write another serializer from Dictionary<string, object>-tree to my class. I would just like to get the JObject that represents my object that is passed as variable to the mutation, but this does not work.

I would also guess that the whole ObjectExtensions are not very fast, because the are based on reflection and not as flexible as JSON.Net.

Therefore my idea is to get rid of Dictionary<string, object> stuff and just use JObject and the Json.Net Serializer.

@joemcbride
Copy link
Member

Are you able to provide an example of what doesn't work for you? This is how this library is currently setup to function:

https://graphql-dotnet.github.io/getting-started/#mutations

public class StarWarsMutation : ObjectGraphType
{
    public StarWarsMutation(StarWarsData data)
    {
        Field<HumanType>(
            "createHuman",
            arguments: new QueryArguments(
                new QueryArgument<NonNullGraphType<HumanInputType>> {Name = "human"}
            ),
            resolve: context =>
            {
                var human = context.GetArgument<Human>("human");
                return data.AddHuman(human);
            });
    }
}

public class HumanInputType : InputObjectGraphType
{
    public HumanInputType()
    {
        Name = "HumanInput";
        Field<NonNullGraphType<StringGraphType>>("name");
        Field<StringGraphType>("homePlanet");
    }
}

public class Human
{
    public string Name { get; set; }
    public string HomePlanet { get; set; }
}

@SebastianStehle
Copy link
Author

SebastianStehle commented Jan 16, 2018

Basically I need

  resolve: context =>
        {
            var human = context.GetArgument<JObject>("human");
            return data.AddHuman(human.ToObject<Human>());
        });

If possible I also would like to skip the valdiation logic. I am writing a headless CMS: https://github.com/squidex/squidex and have custom schemas and validation logic. The query part of graphql already exists since several month, but I have a problem with mutations at the moment.

@joemcbride
Copy link
Member

Have you tried:

var obj = JObject.FromObject(context.Arguments);
var obj = JObject.FromObject(context.Arguments["human"]);

Also, are you expecting there to be values in the Arguments that aren't defined in your GraphQL Schema?

This is the GraphQL spec for how arguments are determined: http://facebook.github.io/graphql/October2016/#sec-Coercing-Field-Arguments

So the values found in ResolveFieldContext.Arguments is determined by the algorithm defined in the spec.

If for whatever reason you're looking to bypass that portion of the spec, the easiest route would be to create a "user context" object and add the raw values to that context.

https://graphql-dotnet.github.io/learn/#user-context

@SebastianStehle
Copy link
Author

This actually works, stupid me. But of course it is not optimal with a lot of conversion steps:

Stream => JObject => Dictionary => JObject

Thanks

@SebastianStehle
Copy link
Author

Works fine, thx

@hasibul2363
Copy link

@SebastianStehle
Could you please share your solution, please. I am very new on GraphQL
What will be possible queryArgument type.
I am also interested to collect an anonymous object from the argument.

new QueryArguments(
                        new QueryArgument<What will be type here> { Name = "model", Description = "anonymous" })

Stream => JObject => Dictionary => JObject
Is it string or stream?

Expecting your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants