Skip to content

Commit 4946310

Browse files
authored
SchemaPrinter can print inputobject default values (graphql-dotnet#2175)
1 parent 0cc0e0b commit 4946310

File tree

3 files changed

+98
-8
lines changed

3 files changed

+98
-8
lines changed

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project>
22

33
<PropertyGroup>
4-
<VersionPrefix>3.3.0-preview</VersionPrefix>
4+
<VersionPrefix>3.3.1-preview</VersionPrefix>
55
<LangVersion>latest</LangVersion>
66
<PackageLicenseExpression>MIT</PackageLicenseExpression>
77
<PackageIcon>logo.64x64.png</PackageIcon>

src/GraphQL.Tests/Utilities/SchemaPrinterTests.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,39 @@ public void prints_input_type()
580580
AssertEqual(print(schema), expected);
581581
}
582582

583+
[Fact]
584+
public void prints_input_type_with_default()
585+
{
586+
var root = new ObjectGraphType { Name = "Query" };
587+
root.Field<NonNullGraphType<StringGraphType>>(
588+
"str",
589+
arguments: new QueryArguments(
590+
new QueryArgument<NonNullGraphType<SomeInputType>> { Name = "argOne", DefaultValue = new SomeInput { Name = "Tom", Age = 42, IsDeveloper = true } },
591+
new QueryArgument<ListGraphType<SomeInputType>> { Name = "argTwo", DefaultValue = new[] { new SomeInput { Name = "Tom1", Age = 12 }, new SomeInput { Name = "Tom2", Age = 22, IsDeveloper = true } } })
592+
);
593+
594+
var schema = new Schema { Query = root };
595+
596+
var expected = new Dictionary<string, string>
597+
{
598+
{
599+
"SomeInput",
600+
@"input SomeInput {
601+
age: Int!
602+
name: String!
603+
isDeveloper: Boolean!
604+
}"
605+
},
606+
{
607+
"Query",
608+
@"type Query {
609+
str(argOne: SomeInput! = { age: 42, name: ""Tom"", isDeveloper: true }, argTwo: [SomeInput] = [{ age: 12, name: ""Tom1"", isDeveloper: false }, { age: 22, name: ""Tom2"", isDeveloper: true }]): String!
610+
}"
611+
},
612+
};
613+
AssertEqual(print(schema), expected);
614+
}
615+
583616
[Fact]
584617
public void prints_custom_scalar()
585618
{
@@ -1015,6 +1048,26 @@ public InputType()
10151048
}
10161049
}
10171050

1051+
public class SomeInputType : InputObjectGraphType<SomeInput>
1052+
{
1053+
public SomeInputType()
1054+
{
1055+
Name = "SomeInput";
1056+
Field(x => x.Age);
1057+
Field(x => x.Name);
1058+
Field(x => x.IsDeveloper);
1059+
}
1060+
}
1061+
1062+
public class SomeInput
1063+
{
1064+
public string Name { get; set; }
1065+
1066+
public int Age { get; set; }
1067+
1068+
public bool IsDeveloper { get; set; }
1069+
}
1070+
10181071
public class OddType : ScalarGraphType
10191072
{
10201073
public OddType()

src/GraphQL/Utilities/SchemaPrinter.cs

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using System.Reflection;
45
using System.Text;
56
using System.Text.RegularExpressions;
67
using GraphQL.Introspection;
78
using GraphQL.Types;
89

910
namespace GraphQL.Utilities
1011
{
11-
public class SchemaPrinter
12+
public class SchemaPrinter //TODO: rewrite string concatenations to use buffer ?
1213
{
1314
protected SchemaPrinterOptions Options { get; }
1415

@@ -165,7 +166,7 @@ public string PrintType(IGraphType type)
165166
IObjectGraphType objectGraphType => PrintObject(objectGraphType),
166167
IInterfaceGraphType interfaceGraphType => PrintInterface(interfaceGraphType),
167168
UnionGraphType unionGraphType => PrintUnion(unionGraphType),
168-
DirectiveGraphType directiveGraphType => PrintDirective(directiveGraphType),
169+
DirectiveGraphType directiveGraphType => PrintDirective(directiveGraphType), //TODO: DirectiveGraphType does not inherit IGraphType
169170
IInputObjectGraphType input => PrintInputObject(input),
170171
_ => throw new InvalidOperationException($"Unknown GraphType '{type.GetType().Name}' with name '{type.Name}'")
171172
};
@@ -292,23 +293,59 @@ public string FormatDefaultValue(object value, IGraphType graphType)
292293
{
293294
return graphType switch
294295
{
295-
NonNullGraphType nullable => FormatDefaultValue(value, nullable.ResolvedType),
296+
NonNullGraphType nonNull => FormatDefaultValue(value, nonNull.ResolvedType),
296297
ListGraphType list => "[{0}]".ToFormat(string.Join(", ", ((IEnumerable<object>)value).Select(i => FormatDefaultValue(i, list.ResolvedType)))),
298+
IInputObjectGraphType input => FormatInputObjectValue(value, input),
297299
EnumerationGraphType enumeration => enumeration.Serialize(value).ToString(),
298-
_ => value switch
300+
ScalarGraphType _ => value switch
299301
{
300302
string s => $"\"{s}\"",
301303
bool b => b ? "true" : "false",
302-
_ => value.ToString()
303-
}
304+
_ => value.ToString() // TODO: how to print custom scalars ("") ?
305+
},
306+
_ => throw new NotSupportedException($"Unsopported graph type '{graphType}'")
304307
};
305308
}
306309

310+
private string FormatInputObjectValue(object value, IInputObjectGraphType input)
311+
{
312+
var sb = new StringBuilder();
313+
sb.Append("{ ");
314+
315+
foreach (var field in input.Fields)
316+
{
317+
string propertyName = field.GetMetadata<string>(ComplexGraphType<object>.ORIGINAL_EXPRESSION_PROPERTY_NAME) ?? field.Name;
318+
PropertyInfo propertyInfo;
319+
320+
try
321+
{
322+
propertyInfo = value.GetType().GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
323+
}
324+
catch (AmbiguousMatchException)
325+
{
326+
propertyInfo = value.GetType().GetProperty(propertyName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
327+
}
328+
329+
object propertyValue = propertyInfo.GetValue(value);
330+
if (propertyValue != null)
331+
{
332+
sb.Append(field.Name)
333+
.Append(": ")
334+
.Append(FormatDefaultValue(propertyValue, field.ResolvedType))
335+
.Append(", ");
336+
}
337+
}
338+
339+
sb.Length -= 2;
340+
sb.Append(" }");
341+
return sb.ToString();
342+
}
343+
307344
public static string ResolveName(IGraphType type)
308345
{
309346
return type switch
310347
{
311-
NonNullGraphType nullable => $"{ResolveName(nullable.ResolvedType)}!",
348+
NonNullGraphType nonNull => $"{ResolveName(nonNull.ResolvedType)}!",
312349
ListGraphType list => $"[{ResolveName(list.ResolvedType)}]",
313350
_ => type?.Name
314351
};

0 commit comments

Comments
 (0)