fix: deal with nested complex types

- make sure the definitions object is the same
  when making recursive calls to generate schema.
  this way all definitions are captured and can
  be referenced correctly.
- add tests for nested complex types
This commit is contained in:
Stevan Freeborn
2024-06-30 15:25:53 -05:00
parent 606c81d384
commit b594927df0
2 changed files with 75 additions and 2 deletions
@@ -68,12 +68,12 @@ static class JsonSchemaGenerator
private static JsonObject GenerateParameterTypeSchema(Type type, JsonObject inputSchema) private static JsonObject GenerateParameterTypeSchema(Type type, JsonObject inputSchema)
{ {
var definitions = inputSchema[DefinitionsKey]; var definitions = inputSchema[DefinitionsKey] ?? new JsonObject();
// Check if a definition for the type already exists // Check if a definition for the type already exists
// If it does, return a reference to the definition // If it does, return a reference to the definition
// no need to evaluate the type further // no need to evaluate the type further
if (definitions is not null && definitions.AsObject().ContainsKey(type.FullName)) if (definitions.AsObject().ContainsKey(type.FullName))
{ {
return new JsonObject() return new JsonObject()
{ {
@@ -150,6 +150,8 @@ static class JsonSchemaGenerator
private static JsonObject GenerateTypeDefinitionSchema(Type type, JsonObject inputSchema) private static JsonObject GenerateTypeDefinitionSchema(Type type, JsonObject inputSchema)
{ {
var definitions = inputSchema[DefinitionsKey] ?? new JsonObject(); var definitions = inputSchema[DefinitionsKey] ?? new JsonObject();
inputSchema[DefinitionsKey] = definitions;
var typeSchema = new JsonObject() var typeSchema = new JsonObject()
{ {
[TypeKey] = ObjectType [TypeKey] = ObjectType
@@ -494,11 +494,82 @@ public class JsonSchemaGeneratorTestData : IEnumerable<object[]>
}, },
} }
}; };
// nested class parameter type with no attributes
yield return new object[]
{
Tool.CreateFromFunction(TestToolName,TestToolDescription,(Family family) => family),
new JsonObject()
{
["type"] = "object",
["definitions"] = new JsonObject()
{
[$"{typeof(Person).FullName}"] = new JsonObject()
{
["type"] = "object",
["properties"] = new JsonObject()
{
["Name"] = new JsonObject()
{
["type"] = "string",
["description"] = string.Empty
},
["Age"] = new JsonObject()
{
["type"] = "integer",
["description"] = string.Empty
}
},
["required"] = new JsonArray()
{
"Name",
"Age"
}
},
[$"{typeof(Family).FullName}"] = new JsonObject()
{
["type"] = "object",
["properties"] = new JsonObject()
{
["Members"] = new JsonObject()
{
["type"] = "array",
["items"] = new JsonObject()
{
["$ref"] = $"#/definitions/{typeof(Person).FullName}"
},
["description"] = string.Empty
}
},
["required"] = new JsonArray()
{
"Members"
}
}
},
["properties"] = new JsonObject()
{
["family"] = new JsonObject()
{
["$ref"] = $"#/definitions/{typeof(Family).FullName}",
["description"] = string.Empty
}
},
["required"] = new JsonArray()
{
"family",
},
}
};
} }
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
} }
class Family
{
public List<Person> Members { get; } = [];
}
class Person class Person
{ {