diff --git a/src/NJsonSchema.CodeGeneration.CSharp/CSharpGenerator.cs b/src/NJsonSchema.CodeGeneration.CSharp/CSharpGenerator.cs
index dfcb8e047..e087f32df 100644
--- a/src/NJsonSchema.CodeGeneration.CSharp/CSharpGenerator.cs
+++ b/src/NJsonSchema.CodeGeneration.CSharp/CSharpGenerator.cs
@@ -29,7 +29,7 @@ public CSharpGenerator(object rootObject)
/// The root object to search for all JSON Schemas.
/// The generator settings.
public CSharpGenerator(object rootObject, CSharpGeneratorSettings settings)
- : this(rootObject, settings, new CSharpTypeResolver(settings))
+ : this(rootObject, settings, new CSharpTypeResolver(rootObject, settings))
{
}
@@ -108,13 +108,13 @@ protected override CodeArtifact GenerateType(JsonSchema schema, string typeNameH
}
else
{
- return GenerateClass(schema, typeName);
+ return GenerateClass(schema, typeName, typeNameHint);
}
}
- private CodeArtifact GenerateClass(JsonSchema schema, string typeName)
+ private CodeArtifact GenerateClass(JsonSchema schema, string typeName, string typeNameHint)
{
- var model = new ClassTemplateModel(typeName, Settings, _resolver, schema, RootObject);
+ var model = new ClassTemplateModel(typeName, typeNameHint, Settings, _resolver, schema, RootObject);
RenamePropertyWithSameNameAsClass(typeName, model.Properties);
diff --git a/src/NJsonSchema.CodeGeneration.CSharp/CSharpTypeResolver.cs b/src/NJsonSchema.CodeGeneration.CSharp/CSharpTypeResolver.cs
index fb26820d8..f77daba66 100644
--- a/src/NJsonSchema.CodeGeneration.CSharp/CSharpTypeResolver.cs
+++ b/src/NJsonSchema.CodeGeneration.CSharp/CSharpTypeResolver.cs
@@ -14,19 +14,24 @@ namespace NJsonSchema.CodeGeneration.CSharp
/// Manages the generated types and converts JSON types to CSharp types.
public class CSharpTypeResolver : TypeResolverBase
{
+ private readonly object _rootObject;
+
/// Initializes a new instance of the class.
+ /// The root object.
/// The generator settings.
- public CSharpTypeResolver(CSharpGeneratorSettings settings)
- : this(settings, null)
+ public CSharpTypeResolver(object rootObject, CSharpGeneratorSettings settings)
+ : this(rootObject, settings, null)
{
}
/// Initializes a new instance of the class.
+ /// The root object.
/// The generator settings.
/// The exception type schema.
- public CSharpTypeResolver(CSharpGeneratorSettings settings, JsonSchema exceptionSchema)
+ public CSharpTypeResolver(object rootObject, CSharpGeneratorSettings settings, JsonSchema exceptionSchema)
: base(settings)
{
+ _rootObject = rootObject;
Settings = settings;
ExceptionSchema = exceptionSchema;
}
@@ -78,7 +83,7 @@ schema is JsonSchemaProperty property &&
var markAsNullableType = Settings.GenerateNullableReferenceTypes && isNullable;
if (schema.ActualTypeSchema.IsAnyType &&
- schema.InheritedSchema == null && // not in inheritance hierarchy
+ schema.GetInheritedSchema(_rootObject) == null && // not in inheritance hierarchy
schema.AllOf.Count == 0 &&
!Types.Keys.Contains(schema) &&
!schema.HasReference)
diff --git a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs
index aaf4a71e9..a1ecf5b45 100644
--- a/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs
+++ b/src/NJsonSchema.CodeGeneration.CSharp/Models/ClassTemplateModel.cs
@@ -17,20 +17,23 @@ public class ClassTemplateModel : ClassTemplateModelBase
{
private readonly CSharpTypeResolver _resolver;
private readonly JsonSchema _schema;
+ private readonly object _rootObject;
private readonly CSharpGeneratorSettings _settings;
/// Initializes a new instance of the class.
/// Name of the type.
+ /// The name to compare the discriminator against.
/// The settings.
/// The resolver.
/// The schema.
/// The root object.
- public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings,
+ public ClassTemplateModel(string typeName, string discriminatorName, CSharpGeneratorSettings settings,
CSharpTypeResolver resolver, JsonSchema schema, object rootObject)
- : base(resolver, schema, rootObject)
+ : base(resolver, schema, rootObject, discriminatorName)
{
_resolver = resolver;
_schema = schema;
+ _rootObject = rootObject;
_settings = settings;
ClassName = typeName;
@@ -39,9 +42,10 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings,
.Select(property => new PropertyModel(this, property, _resolver, _settings))
.ToArray();
- if (schema.InheritedSchema != null)
+ var inheritedSchema = schema.GetInheritedSchema(rootObject);
+ if (inheritedSchema != null)
{
- BaseClass = new ClassTemplateModel(BaseClassName, settings, resolver, schema.InheritedSchema, rootObject);
+ BaseClass = new ClassTemplateModel(BaseClassName, discriminatorName, settings, resolver, inheritedSchema, rootObject);
AllProperties = Properties.Concat(BaseClass.AllProperties).ToArray();
}
else
@@ -102,12 +106,6 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings,
/// Gets a value indicating whether to render ToJson() and FromJson() methods.
public bool GenerateJsonMethods => _settings.GenerateJsonMethods;
- /// Gets a value indicating whether the class has discriminator property.
- public bool HasDiscriminator => !string.IsNullOrEmpty(_schema.ActualDiscriminator);
-
- /// Gets the discriminator property name.
- public string Discriminator => _schema.ActualDiscriminator;
-
/// Gets a value indicating whether this class represents a tuple.
public bool IsTuple => _schema.ActualTypeSchema.IsTuple;
@@ -116,11 +114,8 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings,
.Select(i => _resolver.Resolve(i, i.IsNullable(_settings.SchemaType), string.Empty, false))
.ToArray();
- /// Gets a value indicating whether the class has a parent class.
- public bool HasInheritance => _schema.InheritedTypeSchema != null;
-
/// Gets the base class name.
- public string BaseClassName => HasInheritance ? _resolver.Resolve(_schema.InheritedTypeSchema, false, string.Empty, false)
+ public string BaseClassName => HasInheritance ? _resolver.Resolve(_schema.GetInheritedSchema(_rootObject), false, string.Empty, false)
.Replace(_settings.ArrayType + "<", _settings.ArrayBaseType + "<")
.Replace(_settings.DictionaryType + "<", _settings.DictionaryBaseType + "<") : null;
@@ -129,7 +124,7 @@ public ClassTemplateModel(string typeName, CSharpGeneratorSettings settings,
/// Gets a value indicating whether the class inherits from exception.
public bool InheritsExceptionSchema => _resolver.ExceptionSchema != null &&
- _schema?.InheritsSchema(_resolver.ExceptionSchema) == true;
+ _schema?.InheritsSchema(_resolver.ExceptionSchema, _rootObject) == true;
/// Gets a value indicating whether to use the DateFormatConverter.
public bool UseDateFormatConverter => _settings.DateType.StartsWith("System.Date");
diff --git a/src/NJsonSchema.CodeGeneration.Tests/DefaultValueGeneratorTests.cs b/src/NJsonSchema.CodeGeneration.Tests/DefaultValueGeneratorTests.cs
index ceaf3f07e..be38f380b 100644
--- a/src/NJsonSchema.CodeGeneration.Tests/DefaultValueGeneratorTests.cs
+++ b/src/NJsonSchema.CodeGeneration.Tests/DefaultValueGeneratorTests.cs
@@ -6,20 +6,19 @@ namespace NJsonSchema.CodeGeneration.Tests
{
public class DefaultValueGeneratorTests
{
- private readonly CSharpValueGenerator _csharpGenerator;
- private readonly CSharpTypeResolver _csharpTypeResolver;
+ private readonly CSharpGeneratorSettings _csharpSettings;
+ private readonly CSharpValueGenerator _csharpValueGenerator;
- private readonly TypeScriptValueGenerator _typescriptGenerator;
private readonly TypeScriptGeneratorSettings _typescriptSettings;
+ private readonly TypeScriptValueGenerator _typescriptValueGenerator;
public DefaultValueGeneratorTests()
{
- var csharpSettings = new CSharpGeneratorSettings();
- _csharpTypeResolver = new CSharpTypeResolver(csharpSettings);
- _csharpGenerator = new CSharpValueGenerator(csharpSettings);
+ _csharpSettings = new CSharpGeneratorSettings();
+ _csharpValueGenerator = new CSharpValueGenerator(_csharpSettings);
_typescriptSettings = new TypeScriptGeneratorSettings();
- _typescriptGenerator = new TypeScriptValueGenerator(_typescriptSettings);
+ _typescriptValueGenerator = new TypeScriptValueGenerator(_typescriptSettings);
}
[Fact]
@@ -34,10 +33,10 @@ public void When_schema_has_default_value_of_int_it_is_generated_in_CSharp_and_T
Default = (int)6
};
- var typescriptTypeResolver = new TypeScriptTypeResolver(_typescriptSettings);
+ var typescriptTypeResolver = new TypeScriptTypeResolver(schema, _typescriptSettings);
- var csharpValue = _csharpGenerator.GetDefaultValue(schema, true, "int", "int", true, _csharpTypeResolver);
- var typescriptValue = _typescriptGenerator.GetDefaultValue(schema, true, "int", "int", true, typescriptTypeResolver);
+ var csharpValue = _csharpValueGenerator.GetDefaultValue(schema, true, "int", "int", true, new CSharpTypeResolver(schema, _csharpSettings));
+ var typescriptValue = _typescriptValueGenerator.GetDefaultValue(schema, true, "int", "int", true, typescriptTypeResolver);
//// Assert
Assert.Equal("6", csharpValue);
@@ -57,10 +56,10 @@ public void When_schema_has_default_value_of_long_it_is_generated_in_CSharp_and_
Default = 6000000000L
};
- var typescriptTypeResolver = new TypeScriptTypeResolver(_typescriptSettings);
+ var typescriptTypeResolver = new TypeScriptTypeResolver(schema, _typescriptSettings);
- var csharpValue = _csharpGenerator.GetDefaultValue(schema, true, "long", "long", true, _csharpTypeResolver);
- var typescriptValue = _typescriptGenerator.GetDefaultValue(schema, true, "long", "long", true, typescriptTypeResolver);
+ var csharpValue = _csharpValueGenerator.GetDefaultValue(schema, true, "long", "long", true, new CSharpTypeResolver(schema, _csharpSettings));
+ var typescriptValue = _typescriptValueGenerator.GetDefaultValue(schema, true, "long", "long", true, typescriptTypeResolver);
//// Assert
Assert.Equal("6000000000L", csharpValue);
@@ -80,10 +79,10 @@ public void When_schema_has_default_value_of_double_it_is_generated_in_CSharp_an
Default = 1234.567F
};
- var typescriptTypeResolver = new TypeScriptTypeResolver(_typescriptSettings);
+ var typescriptTypeResolver = new TypeScriptTypeResolver(schema, _typescriptSettings);
- var csharpValue = _csharpGenerator.GetDefaultValue(schema, true, "double", "double", true, _csharpTypeResolver);
- var typescriptValue = _typescriptGenerator.GetDefaultValue(schema, true, "double", "double", true, typescriptTypeResolver);
+ var csharpValue = _csharpValueGenerator.GetDefaultValue(schema, true, "double", "double", true, new CSharpTypeResolver(schema, _csharpSettings));
+ var typescriptValue = _typescriptValueGenerator.GetDefaultValue(schema, true, "double", "double", true, typescriptTypeResolver);
//// Assert
Assert.Equal("1234.567D", csharpValue);
@@ -102,10 +101,10 @@ public void When_schema_has_default_value_of_double_without_format_it_is_generat
Default = 1234.567F
};
- var typescriptTypeResolver = new TypeScriptTypeResolver(_typescriptSettings);
+ var typescriptTypeResolver = new TypeScriptTypeResolver(schema, _typescriptSettings);
- var csharpValue = _csharpGenerator.GetDefaultValue(schema, true, "double", "double", true, _csharpTypeResolver);
- var typescriptValue = _typescriptGenerator.GetDefaultValue(schema, true, "double", "double", true, typescriptTypeResolver);
+ var csharpValue = _csharpValueGenerator.GetDefaultValue(schema, true, "double", "double", true, new CSharpTypeResolver(schema, _csharpSettings));
+ var typescriptValue = _typescriptValueGenerator.GetDefaultValue(schema, true, "double", "double", true, typescriptTypeResolver);
//// Assert
Assert.Equal("1234.567D", csharpValue);
@@ -125,10 +124,10 @@ public void When_schema_has_default_value_of_float_it_is_generated_in_CSharp_and
Default = 1234.567F
};
- var typescriptTypeResolver = new TypeScriptTypeResolver(_typescriptSettings);
+ var typescriptTypeResolver = new TypeScriptTypeResolver(schema, _typescriptSettings);
- var csharpValue = _csharpGenerator.GetDefaultValue(schema, true, "float", "float", true, _csharpTypeResolver);
- var typescriptValue = _typescriptGenerator.GetDefaultValue(schema, true, "float", "float", true, typescriptTypeResolver);
+ var csharpValue = _csharpValueGenerator.GetDefaultValue(schema, true, "float", "float", true, new CSharpTypeResolver(schema, _csharpSettings));
+ var typescriptValue = _typescriptValueGenerator.GetDefaultValue(schema, true, "float", "float", true, typescriptTypeResolver);
//// Assert
Assert.Equal("1234.567F", csharpValue);
@@ -147,10 +146,10 @@ public void When_schema_has_default_value_of_bool_it_is_generated_in_CSharp_and_
Default = true
};
- var typescriptTypeResolver = new TypeScriptTypeResolver(_typescriptSettings);
+ var typescriptTypeResolver = new TypeScriptTypeResolver(schema, _typescriptSettings);
- var csharpValue = _csharpGenerator.GetDefaultValue(schema, true, "bool", "bool", true, _csharpTypeResolver);
- var typescriptValue = _typescriptGenerator.GetDefaultValue(schema, true, "bool", "bool", true, typescriptTypeResolver);
+ var csharpValue = _csharpValueGenerator.GetDefaultValue(schema, true, "bool", "bool", true, new CSharpTypeResolver(schema, _csharpSettings));
+ var typescriptValue = _typescriptValueGenerator.GetDefaultValue(schema, true, "bool", "bool", true, typescriptTypeResolver);
//// Assert
Assert.Equal("true", csharpValue);
@@ -169,10 +168,10 @@ public void When_schema_has_default_value_of_string_it_is_generated_in_CSharp_an
Default = "test\\test\"test\r\ntest"
};
- var typescriptTypeResolver = new TypeScriptTypeResolver(_typescriptSettings);
+ var typescriptTypeResolver = new TypeScriptTypeResolver(schema, _typescriptSettings);
- var csharpValue = _csharpGenerator.GetDefaultValue(schema, true, "string", "string", true, _csharpTypeResolver);
- var typescriptValue = _typescriptGenerator.GetDefaultValue(schema, true, "string", "string", true, typescriptTypeResolver);
+ var csharpValue = _csharpValueGenerator.GetDefaultValue(schema, true, "string", "string", true, new CSharpTypeResolver(schema, _csharpSettings));
+ var typescriptValue = _typescriptValueGenerator.GetDefaultValue(schema, true, "string", "string", true, typescriptTypeResolver);
//// Assert
Assert.Equal("\"test\\\\test\\\"test\\r\\ntest\"", csharpValue);
@@ -191,11 +190,6 @@ public string Generate(int index, string name, object value, JsonSchema schema)
public void When_schema_has_default_value_of_enum_it_is_generated_in_CSharp_and_TypeScript_correctly()
{
//// Arrange
- var csharpSettings = new CSharpGeneratorSettings { EnumNameGenerator = new MyEnumNameGenerator(), Namespace = "Ns" };
- var csharpGenerator = new CSharpValueGenerator(csharpSettings);
- var csharpTypeResolver = new CSharpTypeResolver(csharpSettings);
-
- //// Act
var schema = new JsonSchema()
{
Type = JsonObjectType.String,
@@ -207,9 +201,15 @@ public void When_schema_has_default_value_of_enum_it_is_generated_in_CSharp_and_
Default = "Bar"
};
+ var csharpSettings = new CSharpGeneratorSettings { EnumNameGenerator = new MyEnumNameGenerator(), Namespace = "Ns" };
+ var csharpGenerator = new CSharpValueGenerator(csharpSettings);
+ var csharpTypeResolver = new CSharpTypeResolver(schema, csharpSettings);
+
+ //// Act
+
var typescriptSettings = new TypeScriptGeneratorSettings { EnumNameGenerator = new MyEnumNameGenerator() };
var typescriptGenerator = new TypeScriptValueGenerator(typescriptSettings);
- var typescriptTypeResolver = new TypeScriptTypeResolver(typescriptSettings);
+ var typescriptTypeResolver = new TypeScriptTypeResolver(schema, typescriptSettings);
var csharpValue = csharpGenerator.GetDefaultValue(schema, true, "MyEnum", "MyEnum", true, csharpTypeResolver);
var typescriptValue = typescriptGenerator.GetDefaultValue(schema, true, "MyEnum", "MyEnum", true, typescriptTypeResolver);
diff --git a/src/NJsonSchema.CodeGeneration.Tests/InheritanceSerializationTests.cs b/src/NJsonSchema.CodeGeneration.Tests/InheritanceSerializationTests.cs
index e300829d8..a962fb3a8 100644
--- a/src/NJsonSchema.CodeGeneration.Tests/InheritanceSerializationTests.cs
+++ b/src/NJsonSchema.CodeGeneration.Tests/InheritanceSerializationTests.cs
@@ -11,7 +11,6 @@
using NJsonSchema.CodeGeneration.TypeScript;
using NJsonSchema.Converters;
using Xunit;
-
using System.IO;
using System.Reflection;
using System.CodeDom.Compiler;
diff --git a/src/NJsonSchema.CodeGeneration.TypeScript/Models/ClassTemplateModel.cs b/src/NJsonSchema.CodeGeneration.TypeScript/Models/ClassTemplateModel.cs
index 5bdd00710..ab11ace3c 100644
--- a/src/NJsonSchema.CodeGeneration.TypeScript/Models/ClassTemplateModel.cs
+++ b/src/NJsonSchema.CodeGeneration.TypeScript/Models/ClassTemplateModel.cs
@@ -17,8 +17,8 @@ public class ClassTemplateModel : ClassTemplateModelBase
{
private readonly TypeScriptGeneratorSettings _settings;
private readonly JsonSchema _schema;
+ private readonly object _rootObject;
private readonly TypeScriptTypeResolver _resolver;
- private readonly string _discriminatorName;
/// Initializes a new instance of the class.
/// The type name.
@@ -30,38 +30,24 @@ public class ClassTemplateModel : ClassTemplateModelBase
public ClassTemplateModel(string typeName, string discriminatorName,
TypeScriptGeneratorSettings settings, TypeScriptTypeResolver resolver,
JsonSchema schema, object rootObject)
- : base(resolver, schema, rootObject)
+ : base(resolver, schema, rootObject, discriminatorName)
{
_settings = settings;
_schema = schema;
+ _rootObject = rootObject;
_resolver = resolver;
- _discriminatorName = discriminatorName;
ClassName = typeName;
Properties = _schema.ActualProperties.Values
- .Where(v => settings.TypeStyle == TypeScriptTypeStyle.Interface ||
+ .Where(v => settings.TypeStyle == TypeScriptTypeStyle.Interface ||
v.IsInheritanceDiscriminator == false)
- .Select(property => new PropertyModel(this, property, ClassName, _resolver, _settings))
+ .Select(property => new PropertyModel(this, property, _rootObject, ClassName, _resolver, _settings))
.ToList();
}
/// Gets the class name.
public override string ClassName { get; }
- /// Gets the name for the discriminator check.
- public string DiscriminatorName => HasBaseDiscriminator ?
- (_schema.ResponsibleDiscriminatorObject.Mapping.FirstOrDefault(m => m.Value.ActualTypeSchema == _schema.ActualTypeSchema).Key ?? _discriminatorName) :
- _discriminatorName;
-
- /// Gets a value indicating whether the class has a discriminator property.
- public bool HasDiscriminator => !string.IsNullOrEmpty(_schema.ActualDiscriminator);
-
- /// Gets a value indicating whether the class or an inherited class has a discriminator property.
- public bool HasBaseDiscriminator => _schema.ResponsibleDiscriminatorObject != null;
-
- /// Gets the class discriminator property name (may be defined in a inherited class).
- public string BaseDiscriminator => _schema.ResponsibleDiscriminatorObject?.PropertyName;
-
/// Gets a value indicating whether the class has description.
public bool HasDescription => !(_schema is JsonSchemaProperty) &&
(!string.IsNullOrEmpty(_schema.Description) ||
@@ -72,9 +58,6 @@ public ClassTemplateModel(string typeName, string discriminatorName,
!string.IsNullOrEmpty(_schema.Description) ?
_schema.Description : _schema.ActualTypeSchema.Description);
- /// Gets a value indicating whether this class has a parent class.
- public bool HasInheritance => InheritedSchema != null && !InheritedSchema.IsDictionary;
-
/// Gets the inheritance code.
public string Inheritance
{
@@ -111,7 +94,7 @@ public string Inheritance
/// Gets a value indicating whether the class inherits from dictionary.
public bool HasIndexerProperty => _schema.IsDictionary ||
- _schema.InheritedSchema?.IsDictionary == true;
+ _schema.GetInheritedSchema(_rootObject)?.IsDictionary == true;
/// Gets the type of the indexer property value.
public string IndexerPropertyValueType
@@ -145,8 +128,5 @@ public string IndexerPropertyValueType
/// Gets a value indicating whether the export keyword should be added to all classes.
public bool ExportTypes => _settings.ExportTypes;
-
- /// Gets the inherited schema.
- private JsonSchema InheritedSchema => _schema.InheritedSchema?.ActualSchema;
}
}
\ No newline at end of file
diff --git a/src/NJsonSchema.CodeGeneration.TypeScript/Models/PropertyModel.cs b/src/NJsonSchema.CodeGeneration.TypeScript/Models/PropertyModel.cs
index 5670f7a58..c00c00113 100644
--- a/src/NJsonSchema.CodeGeneration.TypeScript/Models/PropertyModel.cs
+++ b/src/NJsonSchema.CodeGeneration.TypeScript/Models/PropertyModel.cs
@@ -20,22 +20,27 @@ public class PropertyModel : PropertyModelBase
private readonly string _parentTypeName;
private readonly TypeScriptGeneratorSettings _settings;
private readonly JsonSchemaProperty _property;
+ private readonly object _rootObject;
private readonly TypeScriptTypeResolver _resolver;
/// Initializes a new instance of the class.
/// The class template model.
/// The property.
+ /// The root object.
/// Name of the parent type.
/// The resolver.
/// The settings.
public PropertyModel(
ClassTemplateModel classTemplateModel,
- JsonSchemaProperty property, string parentTypeName,
+ JsonSchemaProperty property,
+ object rootObject,
+ string parentTypeName,
TypeScriptTypeResolver typeResolver,
TypeScriptGeneratorSettings settings)
: base(property, classTemplateModel, typeResolver, settings)
{
_property = property;
+ _rootObject = rootObject;
_resolver = typeResolver;
_parentTypeName = parentTypeName;
_settings = settings;
@@ -70,17 +75,17 @@ public bool SupportsConstructorConversion
if (IsArray)
{
- return _resolver.SupportsConstructorConversion(_property.ActualTypeSchema?.Item) &&
+ return _resolver.SupportsConstructorConversion(_property.ActualTypeSchema?.Item, _rootObject) &&
_property.ActualTypeSchema?.Item.ActualSchema.Type.HasFlag(JsonObjectType.Object) == true;
}
if (IsDictionary)
{
- return _resolver.SupportsConstructorConversion(_property.ActualTypeSchema?.AdditionalPropertiesSchema) &&
+ return _resolver.SupportsConstructorConversion(_property.ActualTypeSchema?.AdditionalPropertiesSchema, _rootObject) &&
_property.ActualTypeSchema?.AdditionalPropertiesSchema.ActualSchema.Type.HasFlag(JsonObjectType.Object) == true;
}
- return _resolver.SupportsConstructorConversion(_property) &&
+ return _resolver.SupportsConstructorConversion(_property.ActualTypeSchema, _rootObject) &&
!_property.ActualTypeSchema.IsTuple;
}
}
diff --git a/src/NJsonSchema.CodeGeneration.TypeScript/TypeScriptGenerator.cs b/src/NJsonSchema.CodeGeneration.TypeScript/TypeScriptGenerator.cs
index 53ead3274..d3ebad1ff 100644
--- a/src/NJsonSchema.CodeGeneration.TypeScript/TypeScriptGenerator.cs
+++ b/src/NJsonSchema.CodeGeneration.TypeScript/TypeScriptGenerator.cs
@@ -31,7 +31,7 @@ public TypeScriptGenerator(JsonSchema schema)
/// The root object to search for all JSON Schemas.
/// The generator settings.
public TypeScriptGenerator(object rootObject, TypeScriptGeneratorSettings settings)
- : this(rootObject, settings, new TypeScriptTypeResolver(settings))
+ : this(rootObject, settings, new TypeScriptTypeResolver(rootObject, settings))
{
}
diff --git a/src/NJsonSchema.CodeGeneration.TypeScript/TypeScriptTypeResolver.cs b/src/NJsonSchema.CodeGeneration.TypeScript/TypeScriptTypeResolver.cs
index 51a7390f0..9a41bf02e 100644
--- a/src/NJsonSchema.CodeGeneration.TypeScript/TypeScriptTypeResolver.cs
+++ b/src/NJsonSchema.CodeGeneration.TypeScript/TypeScriptTypeResolver.cs
@@ -14,13 +14,17 @@ namespace NJsonSchema.CodeGeneration.TypeScript
/// Manages the generated types and converts JSON types to TypeScript types.
public class TypeScriptTypeResolver : TypeResolverBase
{
+ private readonly object _rootObject;
+
private const string UnionPipe = " | ";
/// Initializes a new instance of the class.
+ /// The root object.
/// The settings.
- public TypeScriptTypeResolver(TypeScriptGeneratorSettings settings)
+ public TypeScriptTypeResolver(object rootObject, TypeScriptGeneratorSettings settings)
: base(settings)
{
+ _rootObject = rootObject;
Settings = settings;
}
@@ -54,10 +58,11 @@ public override string Resolve(JsonSchema schema, bool isNullable, string typeNa
/// Gets a value indicating whether the schema supports constructor conversion.
/// The schema.
+ /// The root object.
/// The result.
- public bool SupportsConstructorConversion(JsonSchema schema)
+ public bool SupportsConstructorConversion(JsonSchema schema, object rootObject)
{
- return schema?.ActualSchema.ResponsibleDiscriminatorObject == null;
+ return schema?.ActualSchema.GetBaseDiscriminator(rootObject) == null;
}
/// Checks whether the given schema should generate a type.
@@ -85,7 +90,7 @@ private string Resolve(JsonSchema schema, string typeNameHint, bool addInterface
// Primitive schemas (no new type)
if (schema.ActualTypeSchema.IsAnyType &&
- schema.InheritedSchema == null && // not in inheritance hierarchy
+ schema.GetInheritedSchema(_rootObject) == null && // not in inheritance hierarchy
schema.AllOf.Count == 0 &&
!Types.Keys.Contains(schema) &&
!schema.HasReference)
@@ -141,7 +146,7 @@ private string Resolve(JsonSchema schema, string typeNameHint, bool addInterface
if (schema.IsDictionary)
{
var prefix = addInterfacePrefix &&
- SupportsConstructorConversion(schema.AdditionalPropertiesSchema) &&
+ SupportsConstructorConversion(schema.AdditionalPropertiesSchema, _rootObject) &&
schema.AdditionalPropertiesSchema?.ActualSchema.Type.HasFlag(JsonObjectType.Object) == true ? "I" : "";
var valueType = ResolveDictionaryValueType(schema, "any");
@@ -189,8 +194,8 @@ private string Resolve(JsonSchema schema, string typeNameHint, bool addInterface
return string.Join(UnionPipe, types);
}
- return (addInterfacePrefix && !schema.ActualTypeSchema.IsEnumeration && SupportsConstructorConversion(schema) ? "I" : "") +
- GetOrGenerateTypeName(schema, typeNameHint);
+ return (addInterfacePrefix && !schema.ActualTypeSchema.IsEnumeration && SupportsConstructorConversion(schema, _rootObject) ? "I" : "") +
+ base.GetOrGenerateTypeName(schema, typeNameHint);
}
private string ResolveString(JsonSchema schema, string typeNameHint)
@@ -300,7 +305,7 @@ private string ResolveArrayOrTuple(JsonSchema schema, string typeNameHint, bool
{
var isObject = schema.Item?.ActualSchema.Type.HasFlag(JsonObjectType.Object) == true;
var isDictionary = schema.Item?.ActualSchema.IsDictionary == true;
- var prefix = addInterfacePrefix && SupportsConstructorConversion(schema.Item) && isObject && !isDictionary ? "I" : "";
+ var prefix = addInterfacePrefix && SupportsConstructorConversion(schema.Item, _rootObject) && isObject && !isDictionary ? "I" : "";
if (Settings.UseLeafType)
{
diff --git a/src/NJsonSchema.CodeGeneration/JsonSchemaGraphUtilities.cs b/src/NJsonSchema.CodeGeneration/JsonSchemaGraphUtilities.cs
index d17ab260b..6318c4a5e 100644
--- a/src/NJsonSchema.CodeGeneration/JsonSchemaGraphUtilities.cs
+++ b/src/NJsonSchema.CodeGeneration/JsonSchemaGraphUtilities.cs
@@ -20,7 +20,7 @@ public static class JsonSchemaGraphUtilities
///
public static IDictionary GetDerivedSchemas(this JsonSchema schema, object rootObject)
{
- var visitor = new DerivedSchemaVisitor(schema);
+ var visitor = new DerivedSchemaVisitor(schema, rootObject);
visitor.Visit(rootObject);
return visitor.DerivedSchemas;
}
@@ -28,17 +28,19 @@ public static IDictionary GetDerivedSchemas(this JsonSchema
private class DerivedSchemaVisitor : JsonSchemaVisitorBase
{
private readonly JsonSchema _baseSchema;
+ private readonly object _rootObject;
public Dictionary DerivedSchemas { get; } = new Dictionary();
- public DerivedSchemaVisitor(JsonSchema baseSchema)
+ public DerivedSchemaVisitor(JsonSchema baseSchema, object rootObject)
{
_baseSchema = baseSchema;
+ _rootObject = rootObject;
}
protected override JsonSchema VisitSchema(JsonSchema schema, string path, string typeNameHint)
{
- if (schema.Inherits(_baseSchema) && _baseSchema != schema)
+ if (schema.Inherits(_baseSchema, _rootObject) && _baseSchema != schema)
{
DerivedSchemas.Add(schema, typeNameHint);
}
diff --git a/src/NJsonSchema.CodeGeneration/Models/ClassTemplateModelBase.cs b/src/NJsonSchema.CodeGeneration/Models/ClassTemplateModelBase.cs
index 07ac4287e..168954880 100644
--- a/src/NJsonSchema.CodeGeneration/Models/ClassTemplateModelBase.cs
+++ b/src/NJsonSchema.CodeGeneration/Models/ClassTemplateModelBase.cs
@@ -16,22 +16,45 @@ public abstract class ClassTemplateModelBase : TemplateModelBase
{
private readonly JsonSchema _schema;
private readonly object _rootObject;
+ private readonly string _discriminatorName;
private readonly TypeResolverBase _resolver;
/// Initializes a new instance of the class.
/// The resolver.
/// The schema.
/// The root object.
- protected ClassTemplateModelBase(TypeResolverBase resolver, JsonSchema schema, object rootObject)
+ /// The discriminator name.
+ protected ClassTemplateModelBase(TypeResolverBase resolver, JsonSchema schema, object rootObject, string discriminatorName)
{
_schema = schema;
_rootObject = rootObject;
+ _discriminatorName = discriminatorName;
_resolver = resolver;
}
/// Gets the class.
public abstract string ClassName { get; }
+ /// Gets the name for the discriminator check.
+ public string DiscriminatorName => HasBaseDiscriminator ?
+ (_schema.GetBaseDiscriminator(_rootObject)?.Mapping?.FirstOrDefault(m => m.Value.ActualTypeSchema == _schema.ActualTypeSchema).Key ?? _discriminatorName) :
+ _discriminatorName;
+
+ /// Gets a value indicating whether the class has a discriminator property.
+ public bool HasDiscriminator => !string.IsNullOrEmpty(_schema.ActualDiscriminator);
+
+ /// Gets a value indicating whether the class or an inherited class has a discriminator property.
+ public bool HasBaseDiscriminator => _schema.GetBaseDiscriminator(_rootObject) != null;
+
+ /// Gets the class discriminator property name (may be defined in a inherited class).
+ public string BaseDiscriminator => _schema.GetBaseDiscriminator(_rootObject)?.PropertyName;
+
+ /// Gets a value indicating whether this class has a parent class.
+ public bool HasInheritance => InheritedSchema != null && !InheritedSchema.IsDictionary;
+
+ /// Gets the inherited schema.
+ protected JsonSchema InheritedSchema => _schema.GetInheritedSchema(_rootObject)?.ActualSchema;
+
/// Gets a value indicating whether this class represents a JSON object with fixed amount of properties.
public bool IsObject => _schema.ActualTypeSchema.IsObject;
@@ -44,7 +67,7 @@ protected ClassTemplateModelBase(TypeResolverBase resolver, JsonSchema schema, o
/// Gets the derived class names (discriminator key/type name).
public ICollection DerivedClasses => _schema
.GetDerivedSchemas(_rootObject)
- .Select(p => new DerivedClassModel(p.Value, p.Key, _schema.ActualSchema.ResponsibleDiscriminatorObject, _resolver))
+ .Select(p => new DerivedClassModel(p.Value, p.Key, _schema.ActualSchema.GetBaseDiscriminator(_rootObject), _resolver))
.ToList();
/// The model of a derived class.
@@ -52,13 +75,13 @@ public class DerivedClassModel
{
internal DerivedClassModel(string typeName, JsonSchema schema, OpenApiDiscriminator discriminator, TypeResolverBase resolver)
{
- var mapping = discriminator.Mapping.SingleOrDefault(m => m.Value.ActualTypeSchema == schema.ActualTypeSchema);
+ var mapping = discriminator?.Mapping.SingleOrDefault(m => m.Value.ActualTypeSchema == schema.ActualTypeSchema);
ClassName = resolver.GetOrGenerateTypeName(schema, typeName);
IsAbstract = schema.ActualTypeSchema.IsAbstract;
Discriminator =
- mapping.Value != null ? mapping.Key :
+ mapping?.Value != null ? mapping?.Key :
!string.IsNullOrEmpty(typeName) ? typeName :
ClassName;
}
diff --git a/src/NJsonSchema.Demo/NJsonSchema.Demo.csproj b/src/NJsonSchema.Demo/NJsonSchema.Demo.csproj
index cae83be42..5d9c15c48 100644
--- a/src/NJsonSchema.Demo/NJsonSchema.Demo.csproj
+++ b/src/NJsonSchema.Demo/NJsonSchema.Demo.csproj
@@ -9,6 +9,7 @@
+
diff --git a/src/NJsonSchema.Demo/Program.cs b/src/NJsonSchema.Demo/Program.cs
index f3aa0ba70..f06afde33 100644
--- a/src/NJsonSchema.Demo/Program.cs
+++ b/src/NJsonSchema.Demo/Program.cs
@@ -5,6 +5,7 @@
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
+using NJsonSchema.CodeGeneration.Tests;
using NJsonSchema.Benchmark;
namespace NJsonSchema.Demo
@@ -13,6 +14,8 @@ public class Program
{
static void Main(string[] args)
{
+ RunAsync().GetAwaiter().GetResult();
+
Console.BufferHeight = 2000;
var passes = 0;
@@ -72,6 +75,12 @@ static void Main(string[] args)
//Console.ReadLine();
}
+ private static async Task RunAsync()
+ {
+ var x = new InheritanceSerializationTests();
+ await x.When_schema_contains_discriminator_and_inheritance_hierarchy_then_TypeScript_is_correctly_generated();
+ }
+
private static void RunTest(string file, JObject suite, JToken value, bool expectedResult, ref int fails, ref int passes, ref int exceptions)
{
try
diff --git a/src/NJsonSchema.Tests/Generation/ExceptionTypeTests.cs b/src/NJsonSchema.Tests/Generation/ExceptionTypeTests.cs
index 6fbb68672..d8a62d50f 100644
--- a/src/NJsonSchema.Tests/Generation/ExceptionTypeTests.cs
+++ b/src/NJsonSchema.Tests/Generation/ExceptionTypeTests.cs
@@ -21,7 +21,7 @@ public async Task When_exception_schema_is_generated_then_special_properties_are
var json = schema.ToJson();
//// Act
- var exceptionSchema = schema.InheritedSchema.ActualSchema;
+ var exceptionSchema = schema.GetInheritedSchema(schema).ActualSchema;
//// Assert
Assert.True(schema.ActualProperties.ContainsKey("foo"));
diff --git a/src/NJsonSchema.Tests/Generation/InheritanceTests.cs b/src/NJsonSchema.Tests/Generation/InheritanceTests.cs
index 21b80756b..630b7aea1 100644
--- a/src/NJsonSchema.Tests/Generation/InheritanceTests.cs
+++ b/src/NJsonSchema.Tests/Generation/InheritanceTests.cs
@@ -43,7 +43,7 @@ public async Task When_more_properties_are_defined_in_allOf_and_type_none_then_a
var schema = await JsonSchema.FromJsonAsync(json);
//// Assert
- Assert.NotNull(schema.InheritedSchema);
+ Assert.NotNull(schema.GetInheritedSchema(schema));
Assert.Equal(2, schema.ActualProperties.Count);
Assert.True(schema.ActualProperties.ContainsKey("prop1"));
Assert.True(schema.ActualProperties.ContainsKey("prop2"));
@@ -75,7 +75,7 @@ public async Task When_allOf_schema_is_object_type_then_it_is_an_inherited_schem
var schema = await JsonSchema.FromJsonAsync(json);
//// Assert
- Assert.NotNull(schema.InheritedSchema);
+ Assert.NotNull(schema.GetInheritedSchema(schema));
Assert.Equal(1, schema.ActualProperties.Count);
Assert.True(schema.ActualProperties.ContainsKey("prop1"));
}
@@ -367,7 +367,7 @@ public async Task When_class_inherits_from_dictionary_then_allOf_contains_base_d
Assert.Equal(2, bar.AllOf.Count);
Assert.Equal(bar.AllOf.Last(), bar.ActualTypeSchema);
- Assert.Equal(bar.AllOf.First(), bar.InheritedSchema);
+ Assert.Equal(bar.AllOf.First(), bar.GetInheritedSchema(schema));
Assert.True(bar.AllOf.First().IsDictionary); // base class (dictionary)
Assert.True(bar.AllOf.Last().ActualProperties.Any()); // actual class
diff --git a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs
index 45fb0b65b..a34ff3eac 100644
--- a/src/NJsonSchema/Generation/JsonSchemaGenerator.cs
+++ b/src/NJsonSchema/Generation/JsonSchemaGenerator.cs
@@ -541,7 +541,7 @@ protected virtual void GenerateObject(JsonSchema schema, JsonTypeDescription typ
schema.IsAbstract = type.GetTypeInfo().IsAbstract;
}
- GenerateInheritanceDiscriminator(type, rootSchema, schema);
+ GenerateInheritanceDiscriminator(type, rootSchema, schema, schemaResolver);
GenerateKnownTypes(type, schemaResolver);
if (Settings.GenerateXmlObjects)
@@ -1029,7 +1029,7 @@ private JsonSchema GenerateInheritance(ContextualType type, JsonSchema schema, J
GenerateProperties(baseType, schema, schemaResolver);
var actualSchema = GenerateInheritance(baseType, schema, schemaResolver);
- GenerateInheritanceDiscriminator(baseType, schema, actualSchema ?? schema);
+ GenerateInheritanceDiscriminator(baseType, schema, actualSchema ?? schema, schemaResolver);
}
}
else
@@ -1094,7 +1094,7 @@ private JsonSchema GenerateInheritance(ContextualType type, JsonSchema schema, J
GenerateProperties(i, schema, schemaResolver);
var actualSchema = GenerateInheritance(i.ToContextualType(), schema, schemaResolver);
- GenerateInheritanceDiscriminator(i, schema, actualSchema ?? schema);
+ GenerateInheritanceDiscriminator(i, schema, actualSchema ?? schema, schemaResolver);
}
}
}
@@ -1102,7 +1102,7 @@ private JsonSchema GenerateInheritance(ContextualType type, JsonSchema schema, J
return null;
}
- private void GenerateInheritanceDiscriminator(Type type, JsonSchema schema, JsonSchema typeSchema)
+ private void GenerateInheritanceDiscriminator(Type type, JsonSchema schema, JsonSchema typeSchema, JsonSchemaResolver schemaResolver)
{
if (!Settings.GetActualFlattenInheritanceHierarchy(type))
{
@@ -1142,7 +1142,7 @@ private void GenerateInheritanceDiscriminator(Type type, JsonSchema schema, Json
}
else
{
- var baseDiscriminator = schema.ResponsibleDiscriminatorObject ?? schema.ActualTypeSchema.ResponsibleDiscriminatorObject;
+ var baseDiscriminator = schema.GetBaseDiscriminator(schemaResolver.RootObject);
baseDiscriminator?.AddMapping(type, schema);
}
}
diff --git a/src/NJsonSchema/JsonSchema.Reference.cs b/src/NJsonSchema/JsonSchema.Reference.cs
index 182167ffc..467526797 100644
--- a/src/NJsonSchema/JsonSchema.Reference.cs
+++ b/src/NJsonSchema/JsonSchema.Reference.cs
@@ -130,7 +130,9 @@ private JsonSchema GetActualSchema(IList checkedSchemas)
/// Gets the parent object of this object.
[JsonIgnore]
- object IJsonReference.PossibleRoot => Parent;
+ object IJsonReference.PossibleRoot => Parent != this && Parent is IJsonReference reference ?
+ reference.PossibleRoot :
+ Parent; // TODO: Avoid cycles
/// Gets or sets the referenced object.
[JsonIgnore]
diff --git a/src/NJsonSchema/JsonSchema.cs b/src/NJsonSchema/JsonSchema.cs
index e5750d6ca..1a2f7464f 100644
--- a/src/NJsonSchema/JsonSchema.cs
+++ b/src/NJsonSchema/JsonSchema.cs
@@ -20,6 +20,7 @@
using NJsonSchema.Collections;
using NJsonSchema.Generation;
using NJsonSchema.Infrastructure;
+using NJsonSchema.References;
using NJsonSchema.Validation;
using NJsonSchema.Validation.FormatValidators;
@@ -227,87 +228,6 @@ public bool IsBinary
}
}
- /// Gets the inherited/parent schema (most probable base schema in allOf).
- /// Used for code generation.
- [JsonIgnore]
- public JsonSchema InheritedSchema
- {
- get
- {
- if (AllOf == null || AllOf.Count == 0 || HasReference)
- {
- return null;
- }
-
- if (AllOf.Count == 1)
- {
- return AllOf.First().ActualSchema;
- }
-
- if (AllOf.Any(s => s.HasReference))
- {
- return AllOf.First(s => s.HasReference).ActualSchema;
- }
-
- if (AllOf.Any(s => s.Type.HasFlag(JsonObjectType.Object)))
- {
- return AllOf.First(s => s.Type.HasFlag(JsonObjectType.Object)).ActualSchema;
- }
-
- return AllOf.FirstOrDefault()?.ActualSchema;
- }
- }
-
- /// Gets the inherited/parent schema which may also be inlined
- /// (the schema itself if it is a dictionary or array, otherwise ).
- /// Used for code generation.
- [JsonIgnore]
- public JsonSchema InheritedTypeSchema
- {
- get
- {
- if (ActualTypeSchema.IsDictionary || ActualTypeSchema.IsArray || ActualTypeSchema.IsTuple)
- {
- return ActualTypeSchema;
- }
-
- return InheritedSchema;
- }
- }
-
- /// Gets the list of all inherited/parent schemas.
- /// Used for code generation.
- [JsonIgnore]
-#if !LEGACY
- public IReadOnlyCollection AllInheritedSchemas
-#else
- public ICollection AllInheritedSchemas
-#endif
- {
- get
- {
- var inheritedSchema = this.InheritedSchema != null ?
- new List { this.InheritedSchema } :
- new List();
-
- return inheritedSchema.Concat(inheritedSchema.SelectMany(s => s.AllInheritedSchemas)).ToList();
- }
- }
-
- /// Determines whether the given schema is the parent schema of this schema (i.e. super/base class).
- /// The possible subtype schema.
- /// true or false
- public bool Inherits(JsonSchema schema)
- {
- schema = schema.ActualSchema;
- return InheritedSchema?.ActualSchema == schema || InheritedSchema?.Inherits(schema) == true;
- }
-
- /// Gets the discriminator or discriminator of an inherited schema (or null).
- [JsonIgnore]
- public OpenApiDiscriminator ResponsibleDiscriminatorObject =>
- ActualDiscriminatorObject ?? InheritedSchema?.ActualSchema.ResponsibleDiscriminatorObject;
-
/// Gets all properties of this schema (i.e. all direct properties and properties from the schemas in allOf which do not have a type).
/// Used for code generation.
/// Some properties are defined multiple times.
@@ -321,7 +241,7 @@ public IDictionary ActualProperties
get
{
var properties = Properties
- .Union(AllOf.Where(s => s.ActualSchema != InheritedSchema)
+ .Union(AllOf.Where(s => s.ActualSchema != this.GetInheritedSchema(((IJsonReference)this).PossibleRoot))
.SelectMany(s => s.ActualSchema.ActualProperties))
.ToList();
@@ -857,16 +777,6 @@ public JToken ToSampleJson()
// return json;
//}
- /// Gets a value indicating whether this schema inherits from the given parent schema.
- /// The parent schema.
- /// true or false.
- public bool InheritsSchema(JsonSchema parentSchema)
- {
- return parentSchema != null && ActualSchema
- .AllInheritedSchemas.Concat(new List { this })
- .Any(s => s.ActualSchema == parentSchema.ActualSchema) == true;
- }
-
/// Validates the given JSON data against this schema.
/// The JSON data to validate.
/// Custom validators to validate the JSON.
diff --git a/src/NJsonSchema/JsonSchemaExtensions.cs b/src/NJsonSchema/JsonSchemaExtensions.cs
new file mode 100644
index 000000000..4ad9494cc
--- /dev/null
+++ b/src/NJsonSchema/JsonSchemaExtensions.cs
@@ -0,0 +1,166 @@
+//-----------------------------------------------------------------------
+//
+// Copyright (c) Rico Suter. All rights reserved.
+//
+// https://github.com/rsuter/NJsonSchema/blob/master/LICENSE.md
+// Rico Suter, mail@rsuter.com
+//-----------------------------------------------------------------------
+
+using System.Collections.Generic;
+using System.Linq;
+using NJsonSchema.Visitors;
+
+namespace NJsonSchema
+{
+ /// JSON Schema graph utilities.
+ public static class JsonSchemaExtensions
+ {
+ /// Gets a value indicating whether this schema inherits from the given parent schema.
+ /// The schema.
+ /// The possible parent schema.
+ /// The root object.
+ /// true or false.
+ public static bool InheritsSchema(this JsonSchema schema, JsonSchema parentSchema, object rootObject)
+ {
+ return parentSchema != null && schema.ActualSchema
+ .GetAllInheritedSchemas(rootObject)
+ .Concat(new List { schema })
+ .Any(s => s.ActualSchema == parentSchema.ActualSchema) == true;
+ }
+
+ /// Gets the inherited/parent schema (most probable base schema in allOf).
+ /// Used for code generation.
+ public static JsonSchema GetInheritedSchema(this JsonSchema schema, object rootObject)
+ {
+ if (schema.HasReference)
+ return null;
+
+ if (schema.AllOf == null || schema.AllOf.Count == 0)
+ return rootObject != null ? schema.GetOneOfInheritedSchema(rootObject) : null;
+
+ if (schema.AllOf.Count == 1)
+ return schema.AllOf.First().ActualSchema;
+
+ if (schema.AllOf.Any(s => s.HasReference && !s.ActualSchema.IsAnyType))
+ return schema.AllOf.First(s => s.HasReference && !s.ActualSchema.IsAnyType).ActualSchema;
+
+ if (schema.AllOf.Any(s => s.Type.HasFlag(JsonObjectType.Object) && !s.ActualSchema.IsAnyType))
+ return schema.AllOf.First(s => s.Type.HasFlag(JsonObjectType.Object) && !s.ActualSchema.IsAnyType).ActualSchema;
+
+ return schema.AllOf.First(s => !s.ActualSchema.IsAnyType)?.ActualSchema ??
+ (rootObject != null ? schema.GetOneOfInheritedSchema(rootObject) : null);
+ }
+
+ /// Gets the list of all inherited/parent schemas.
+ /// Used for code generation.
+#if !LEGACY
+ public static IReadOnlyCollection GetAllInheritedSchemas(this JsonSchema schema, object rootObject)
+#else
+ public static ICollection GetAllInheritedSchemas(this JsonSchema schema, object rootObject)
+#endif
+ {
+ var inheritedSchema = schema.GetInheritedSchema(rootObject) != null ?
+ new List { schema.GetInheritedSchema(rootObject) } :
+ new List();
+
+ return inheritedSchema.Concat(inheritedSchema.SelectMany(s => s.GetAllInheritedSchemas(rootObject))).ToList();
+ }
+
+ /// Determines whether the given schema is the parent schema of this schema (i.e. super/base class).
+ /// The schema.
+ /// The possible subtype schema.
+ /// The root object needed to scan oneOf properties.
+ /// true or false
+ public static bool Inherits(this JsonSchema schema, JsonSchema inheritedSchema, object rootObject)
+ {
+ inheritedSchema = inheritedSchema.ActualSchema;
+ return schema.GetInheritedSchema(rootObject)?.ActualSchema == inheritedSchema ||
+ schema.GetInheritedSchema(rootObject)?.Inherits(inheritedSchema, rootObject) == true;
+ }
+
+ /// Gets the discriminator or discriminator of an inherited schema (or null).
+ public static OpenApiDiscriminator GetBaseDiscriminator(this JsonSchema schema, object rootObject)
+ {
+ return schema.DiscriminatorObject ?? schema.GetInheritedSchema(rootObject)?.ActualSchema.GetBaseDiscriminator(rootObject);
+ }
+
+ /// Gets the derived schemas.
+ /// The schema.
+ /// The root object.
+ ///
+ public static IDictionary GetDerivedSchemas(this JsonSchema schema, object rootObject)
+ {
+ var visitor = new DerivedSchemaVisitor(schema, rootObject);
+ visitor.Visit(rootObject);
+ return visitor.DerivedSchemas;
+ }
+
+ private class DerivedSchemaVisitor : JsonSchemaVisitorBase
+ {
+ private readonly JsonSchema _baseSchema;
+ private readonly object _rootObject;
+
+ public Dictionary DerivedSchemas { get; } = new Dictionary();
+
+ public DerivedSchemaVisitor(JsonSchema baseSchema, object rootObject)
+ {
+ _baseSchema = baseSchema;
+ _rootObject = rootObject;
+ }
+
+ protected override JsonSchema VisitSchema(JsonSchema schema, string path, string typeNameHint)
+ {
+ if (schema.Inherits(_baseSchema, _rootObject) && _baseSchema != schema)
+ DerivedSchemas.Add(schema, typeNameHint);
+
+ return schema;
+ }
+ }
+
+
+ /// Gets the schemas which are inherited via oneOf.
+ /// The schema.
+ /// The root object.
+ ///
+ public static JsonSchema GetOneOfInheritedSchema(this JsonSchema schema, object rootObject)
+ {
+ return schema.GetOneOfInheritedSchemas(rootObject)?.FirstOrDefault().Key;
+ }
+
+ /// Gets the schemas which are inherited via oneOf.
+ /// The schema.
+ /// The root object.
+ ///
+ public static IDictionary GetOneOfInheritedSchemas(this JsonSchema schema, object rootObject)
+ {
+ var visitor = new InheritedSchemaVisitor(schema);
+ visitor.Visit(rootObject);
+ return visitor.InheritedSchemas;
+ }
+
+ private class InheritedSchemaVisitor : JsonSchemaVisitorBase
+ {
+ private readonly JsonSchema _schema;
+
+ public Dictionary InheritedSchemas { get; } = new Dictionary();
+
+ public InheritedSchemaVisitor(JsonSchema schema)
+ {
+ _schema = schema;
+ }
+
+ protected override JsonSchema VisitSchema(JsonSchema schema, string path, string typeNameHint)
+ {
+ if (schema.OneOf.Any(s => s.ActualSchema == _schema.ActualSchema))
+ {
+ if (schema.OneOf.All(s => s.ActualSchema.Type == JsonObjectType.Object))
+ {
+ InheritedSchemas.Add(schema, typeNameHint);
+ }
+ }
+
+ return schema;
+ }
+ }
+ }
+}
\ No newline at end of file