graphql-dotnet/parser - Getting the field types to string from an ASTNode

749 Views Asked by At

Ok, so I've been at this for hours and exshausted all of the documentation I could lay eyes on without an answer.

The ASTNode resulting from parsing a graphql schema using graphql-dotnet/parser has field properties. In previous releases of the library, you could easily get the Name and Type of a field with Field.Name.Value.ToString() and Field.Type.ToString() respectively.

In 8.1.0, the Field property is more complex and Field.Type.ToString() returns GraphQLParser.AST.GraphQLNamedTypeFull. I am therefore struggling to reliably get the Typename for parsed GraphQL shema type fields.

More information below:

Basically, I have a library that reads in a large GraphQL schema file and parses it. It then generates .NET class files for all of the types, enums, interfaces etc. found in the schema. I've had this working flawlessly for about a year now.

I've today decided to update the graphql-dotnet/parser library version to 8.1.0 and immediately had compile-time failures. So we have some breaking changes between versions, at lease in the way that I was using the 7.x version of the parser library, no big deal. I fixed the compile-time issue and thought I was home free. Until I inspected the resulting classes coming out of my autogen process. To my surprise, all of the class properties/fields (of all resulting 3907 class files) are now of type: GraphQLParser.AST.GraphQLNamedTypeFull (i.e. private GraphQLParser.AST.GraphQLNamedTypeFull _isEulaAccepted;)

Upon inspection I found the lines responsible for generating this in my code:

foreach (GraphQLFieldDefinition field in fields)
{
    if (field != null && field.Type != null)
    {
        members.Add(ConvertParamName(field.Name.Value.ToString()), ConvertTypeName(field.Type.ToString()));
    }
}

The problem statement is field.Type.ToString()

In previous releases of graphql-dotnet/parser, that statement would return the type of the field (i.e. String, Int, Bool, Aeroplane, Car, etc.) as a string. It looks as if in version 8.1.0 or the library, the Field property on the ASTNode is now more complex, with nested "Type" properties.

Serializing the field object as JSON at runtime shows what it turns up as:

{
   "Location":{
      "Start":162,
      "End":178
   },
   "Comments":null,
   "Kind":28,
   "Arguments":null,
   "Type":{
      "Location":{
         "Start":171,
         "End":178
      },
      "Comments":null,
      "Kind":22,
      "Type":{
         "Location":{
            "Start":171,
            "End":177
         },
         "Comments":null,
         "Kind":20,
         "Name":{
            "Location":{
               "Start":171,
               "End":177
            },
            "Comments":null,
            "Kind":0,
            "Value":{
               "Length":6,
               "IsEmpty":false
            },
            "StringValue":"String"
         }
      }
   },
   "Directives":null,
   "Description":null,
   "Name":{
      "Location":{
         "Start":162,
         "End":169
      },
      "Comments":null,
      "Kind":0,
      "Value":{
         "Length":7,
         "IsEmpty":false
      },
      "StringValue":"version"
   }
}

The problem is, that it's only nested at complile time, so I cannot walk the tree as:

field.Type.Type.Name.Type.StringValue

I've tried looking for methods or helpers to get this value out reliably, but to no avail.

The best I could come up with is:

string myField = JsonConvert.SerializeObject(field);
JObject myObj = JObject.Parse(myField);
String typeName = myObj["Type"]["Type"]["Name"]["StringValue"]

It doesn't work well, as it seems the object is different for some nodes.

I've spent hours digging though the examples on https://github.com/graphql-dotnet/graphql-dotnet and more hours reading the library source code at https://github.com/graphql-dotnet/parser.

Any idea as to how a I can get around this issue?

Thanks

1

There are 1 best solutions below

0
On

You could use ASTNode.Location to get the original string content from the schema like this (pseudo-code):

var typeAsString = "your schema".SubString(field.Type.Location.Start, field.Type.Location.End - field.Type.Location.Start); 

Hope it helps!