in src/Json.Schema.ToDotNet/PropertyInfoDictionary.cs [214:385]
private void AddPropertyInfoFromPropertySchema(
IList<KeyValuePair<string, PropertyInfo>> entries,
string schemaPropertyName,
JsonSchema propertySchema,
bool isRequired)
{
ComparisonKind comparisonKind;
HashKind hashKind;
InitializationKind initializationKind;
TypeSyntax type;
string namespaceName = null;
string referencedEnumTypeName;
bool isOfSchemaDefinedType = false;
int arrayRank = 0;
if (propertySchema.IsDateTime())
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakeNamedType("System.DateTime", out namespaceName);
}
else if (propertySchema.IsUri())
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarReferenceType;
initializationKind = InitializationKind.Uri;
type = MakeNamedType("System.Uri", out namespaceName);
}
else if (propertySchema.ShouldBeDictionary(_typeName, schemaPropertyName, _hintDictionary, out DictionaryHint dictionaryHint))
{
comparisonKind = ComparisonKind.Dictionary;
hashKind = HashKind.Dictionary;
initializationKind = InitializationKind.Dictionary;
// If the schema for this property specifies additionalProperties, and if
// the value of additionalProperties is a schema as opposed to a Boolean,
// then we will represent this property as a dictionary from string to
// whatever kind of object the schema represents. Otherwise, treat it as
// a dictionary from string to string.
JsonSchema dictionaryElementSchema = propertySchema.AdditionalProperties?.Schema != null
? propertySchema.AdditionalProperties.Schema
: new JsonSchema { Type = new SchemaType[] { SchemaType.String } };
type = MakeDictionaryType(entries, schemaPropertyName, dictionaryHint, dictionaryElementSchema);
namespaceName = "System.Collections.Generic"; // For IDictionary.
}
else if ((referencedEnumTypeName = GetReferencedEnumTypeName(propertySchema)) != null)
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakeNamedType(referencedEnumTypeName, out namespaceName);
}
else if (propertySchema.ShouldBeEnum(_typeName, schemaPropertyName, _hintDictionary, out EnumHint enumHint))
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakeNamedType(enumHint.TypeName, out namespaceName);
// The class whose property info we are generating contains a property
// of an enumerated type. Notify the code generator that it must generate
// the enumerated type in addition to the current type.
OnAdditionalTypeRequired(enumHint, propertySchema);
}
else
{
SchemaType propertyType = propertySchema.SafeGetType();
switch (propertyType)
{
case SchemaType.Boolean:
case SchemaType.Integer:
case SchemaType.Number:
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakePrimitiveType(propertyType);
break;
case SchemaType.String:
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarReferenceType;
initializationKind = InitializationKind.SimpleAssign;
type = MakePrimitiveType(propertyType);
break;
case SchemaType.Object:
// If the schema for this property references a named type,
// the generated Init method will initialize it by cloning an object
// of that type. Otherwise, we treat this property as a System.Object
// and just initialize it by assignment.
if (propertySchema.Reference != null)
{
comparisonKind = ComparisonKind.EqualityComparerEquals;
initializationKind = InitializationKind.Clone;
hashKind = HashKind.ObjectModelType;
isOfSchemaDefinedType = true;
}
else
{
comparisonKind = ComparisonKind.ObjectEquals;
initializationKind = InitializationKind.SimpleAssign;
hashKind = HashKind.ScalarReferenceType;
}
type = MakeObjectType(propertySchema, out namespaceName);
break;
case SchemaType.Array:
comparisonKind = ComparisonKind.Collection;
hashKind = HashKind.Collection;
initializationKind = InitializationKind.Collection;
namespaceName = "System.Collections.Generic"; // For IList.
type = MakeArrayType(entries, schemaPropertyName, propertySchema);
break;
case SchemaType.None:
SchemaType inferredType = InferSchemaTypeFromEnumValues(propertySchema.Enum);
if (inferredType == SchemaType.None)
{
comparisonKind = ComparisonKind.ObjectEquals;
hashKind = HashKind.ScalarReferenceType;
initializationKind = InitializationKind.None;
type = MakePrimitiveType(SchemaType.Object);
break;
}
else if (inferredType == SchemaType.String)
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarReferenceType;
initializationKind = InitializationKind.SimpleAssign;
type = MakePrimitiveType(SchemaType.String);
break;
}
else
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakePrimitiveType(inferredType);
break;
}
default:
throw new ArgumentOutOfRangeException(nameof(propertySchema.Type));
}
}
var propertyNameHint = _hintDictionary?.GetHint<PropertyNameHint>(_typeName + "." + schemaPropertyName);
string dotNetPropertyName = propertyNameHint != null
? propertyNameHint.DotNetPropertyName
: schemaPropertyName.ToPascalCase();
entries.Add(new KeyValuePair<string, PropertyInfo>(
dotNetPropertyName,
new PropertyInfo(
propertySchema.Description,
schemaPropertyName,
comparisonKind,
hashKind,
initializationKind,
type,
namespaceName,
isRequired,
propertySchema.Default,
isOfSchemaDefinedType,
arrayRank,
entries.Count)));
}