FEATURE: Merge `HintKind`: `PropertyNameHint` and `PropertyModifiersHint` into one `PropertyHint` and Add a new setting `typeName` (#171)

* Add GenerateJsonIntegerAsHint

* Update naming

* rename to `TypeName`

* SupportedPropertyTypeHint

* PropertyTypeHintTests

* Add tests

* Fix test

* add tests

* Release History

* Update tests

* Add tests

* Merge `HintKind`: `PropertyNameHint` and `PropertyModifiersHint` into one `PropertyHint`

* Update names

* Add test

* fix over write issue

* Fix case
This commit is contained in:
Shaopeng 2023-07-27 13:23:45 -07:00 коммит произвёл GitHub
Родитель ca09cfafcf
Коммит d65f4a9f51
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
15 изменённых файлов: 473 добавлений и 223 удалений

Просмотреть файл

@ -42,7 +42,7 @@ namespace Microsoft.Json.Schema.ToDotNet.Hints.UnitTests
],
""C.Value2"": [
{
""kind"": ""PropertyModifiersHint"",
""kind"": ""PropertyHint"",
""arguments"": {
""modifiers"": [
""internal""

Просмотреть файл

@ -5,7 +5,7 @@ using Xunit;
namespace Microsoft.Json.Schema.ToDotNet.Hints.UnitTests
{
public class PropertyModifiersHintTests : HintTestBase
public class PropertyHintModifiersTests : HintTestBase
{
public static readonly TheoryData<HintTestCase> TestCases = new TheoryData<HintTestCase>
{
@ -23,7 +23,7 @@ namespace Microsoft.Json.Schema.ToDotNet.Hints.UnitTests
@"{
""C.TheProperty"": [
{
""kind"": ""PropertyModifiersHint"",
""kind"": ""PropertyHint"",
""arguments"": {
""modifiers"": [
]
@ -62,7 +62,7 @@ namespace N
@"{
""C.TheProperty"": [
{
""kind"": ""PropertyModifiersHint"",
""kind"": ""PropertyHint"",
""arguments"": {
""modifiers"": [
""internal""
@ -102,7 +102,7 @@ namespace N
@"{
""C.TheProperty"": [
{
""kind"": ""PropertyModifiersHint"",
""kind"": ""PropertyHint"",
""arguments"": {
""modifiers"": [
""internal"",
@ -143,7 +143,7 @@ namespace N
@"{
""C.TheProperty"": [
{
""kind"": ""PropertyModifiersHint"",
""kind"": ""PropertyHint"",
""arguments"": {
""modifiers"": [
""invalid_modifier""
@ -172,7 +172,7 @@ namespace N
@"{
""*.TheProperty"": [
{
""kind"": ""PropertyModifiersHint"",
""kind"": ""PropertyHint"",
""arguments"": {
""modifiers"": [
""internal"",
@ -200,9 +200,9 @@ namespace N
),
};
[Theory(DisplayName = nameof(PropertyModifiersHint))]
[Theory(DisplayName = nameof(PropertyHintModifiersTest))]
[MemberData(nameof(TestCases))]
public void PropertyModifiersHint(HintTestCase testCase)
public void PropertyHintModifiersTest(HintTestCase testCase)
{
RunHintTestCase(testCase);
}

Просмотреть файл

@ -5,7 +5,7 @@ using Xunit;
namespace Microsoft.Json.Schema.ToDotNet.Hints.UnitTests
{
public class PropertyNameHintTests : HintTestBase
public class PropertyHintNameTests : HintTestBase
{
public static readonly TheoryData<HintTestCase> TestCases = new TheoryData<HintTestCase>
{
@ -24,9 +24,9 @@ namespace Microsoft.Json.Schema.ToDotNet.Hints.UnitTests
@"{
""C.$schema"": [
{
""kind"": ""PropertyNameHint"",
""kind"": ""PropertyHint"",
""arguments"": {
""dotNetPropertyName"": ""SchemaUri""
""name"": ""SchemaUri""
}
}
]
@ -45,51 +45,13 @@ namespace N
[DataMember(Name = ""$schema"", IsRequired = false, EmitDefaultValue = false)]
public Uri SchemaUri { get; set; }
}
}"
),
new HintTestCase(
"Specifies integer property name",
@"{
""type"": ""object"",
""properties"": {
""itemCount"": {
""type"": ""integer""
}
}
}",
@"{
""C.ItemCount"": [
{
""kind"": ""PropertyNameHint"",
""arguments"": {
""dotNetPropertyName"": ""RenamedItemCount""
}
}
]
}",
@"using System;
using System.CodeDom.Compiler;
using System.Runtime.Serialization;
namespace N
{
[DataContract]
[GeneratedCode(""Microsoft.Json.Schema.ToDotNet"", """ + VersionConstants.FileVersion + @""")]
public partial class C
{
[DataMember(Name = ""itemCount"", IsRequired = false, EmitDefaultValue = false)]
public int? RenamedItemCount { get; set; }
}
}"
)
};
[Theory(DisplayName = nameof(PropertyNameHint))]
[Theory(DisplayName = nameof(PropertyHintNameTest))]
[MemberData(nameof(TestCases))]
public void PropertyNameHint(HintTestCase testCase)
public void PropertyHintNameTest(HintTestCase testCase)
{
RunHintTestCase(testCase);
}

Просмотреть файл

@ -0,0 +1,64 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Xunit;
namespace Microsoft.Json.Schema.ToDotNet.Hints.UnitTests
{
public class PropertyHintTests : HintTestBase
{
public static readonly TheoryData<HintTestCase> TestCases = new TheoryData<HintTestCase>
{
new HintTestCase(
"Specifies property name",
@"{
""type"": ""object"",
""properties"": {
""TheNullableBigIntegerProperty"": {
""type"": ""integer""
},
}
}",
@"{
""C.TheNullableBigIntegerProperty"": [
{
""kind"": ""PropertyHint"",
""arguments"": {
""modifiers"": [
""internal"",
""override""
],
""typeName"": ""BigInteger"",
""name"": ""OverrideTheNullableBigIntegerProperty""
}
}
]
}",
@"using System;
using System.CodeDom.Compiler;
using System.Numerics;
using System.Runtime.Serialization;
namespace N
{
[DataContract]
[GeneratedCode(""Microsoft.Json.Schema.ToDotNet"", """ + VersionConstants.FileVersion + @""")]
public partial class C
{
[DataMember(Name = ""TheNullableBigIntegerProperty"", IsRequired = false, EmitDefaultValue = false)]
internal override BigInteger? OverrideTheNullableBigIntegerProperty { get; set; }
}
}"
)
};
[Theory(DisplayName = nameof(PropertyHintTest))]
[MemberData(nameof(TestCases))]
public void PropertyHintTest(HintTestCase testCase)
{
RunHintTestCase(testCase);
}
}
}

Просмотреть файл

@ -0,0 +1,185 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Xunit;
namespace Microsoft.Json.Schema.ToDotNet.Hints.UnitTests
{
public class PropertyHintTypeNameTests : HintTestBase
{
public static readonly TheoryData<HintTestCase> TestCases = new TheoryData<HintTestCase>
{
new HintTestCase(
"Specifies property name",
@"{
""type"": ""object"",
""properties"": {
""TheNullableBigIntegerProperty"": {
""type"": ""integer""
},
""TheBigIntegerProperty"": {
""type"": ""integer"",
""default"": ""-1""
},
""TheIntegerProperty"": {
""type"": ""integer"",
""default"": ""-1"",
},
""TheLongProperty"": {
""type"": ""integer"",
""default"": ""-1""
},
""TheStringProperty"": {
""type"": ""integer"",
""default"": ""-1""
},
""TheNullableGuidProperty"": {
""type"": ""string""
},
""TheUriProperty"": {
""type"": ""string""
},
""TheBoolStringProperty"": {
""type"": ""boolean""
},
""TheStringBoolProperty"": {
""type"": ""string""
},
""TheDecimalProperty"": {
""type"": ""number"",
""default"": ""1.11111""
},
""TheDoubleProperty"": {
""type"": ""number"",
""default"": ""1.11111""
},
}
}",
@"{
""C.TheNullableBigIntegerProperty"": [
{
""kind"": ""PropertyHint"",
""arguments"": {
""typeName"": ""BigInteger""
}
}
],
""C.TheLongProperty"": [
{
""kind"": ""PropertyHint"",
""arguments"": {
""typeName"": ""Long""
}
}
],
""C.TheStringProperty"": [
{
""kind"": ""PropertyHint"",
""arguments"": {
""typeName"": ""String""
}
}
],
""C.TheNullableGuidProperty"": [
{
""kind"": ""PropertyHint"",
""arguments"": {
""typeName"": ""Guid""
}
}
],
""C.TheUriProperty"": [
{
""kind"": ""PropertyHint"",
""arguments"": {
""typeName"": ""Uri""
}
}
],
""C.TheBoolStringProperty"": [
{
""kind"": ""PropertyHint"",
""arguments"": {
""typeName"": ""String""
}
}
],
""C.TheStringBoolProperty"": [
{
""kind"": ""PropertyHint"",
""arguments"": {
""typeName"": ""Bool""
}
}
],
""C.TheDecimalProperty"": [
{
""kind"": ""PropertyHint"",
""arguments"": {
""typeName"": ""Decimal""
}
}
]
}",
@"using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Numerics;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace N
{
[DataContract]
[GeneratedCode(""Microsoft.Json.Schema.ToDotNet"", """ + VersionConstants.FileVersion + @""")]
public partial class C
{
[DataMember(Name = ""TheNullableBigIntegerProperty"", IsRequired = false, EmitDefaultValue = false)]
public BigInteger? TheNullableBigIntegerProperty { get; set; }
[DataMember(Name = ""TheBigIntegerProperty"", IsRequired = false, EmitDefaultValue = false)]
[DefaultValue(""-1"")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public int TheBigIntegerProperty { get; set; }
[DataMember(Name = ""TheIntegerProperty"", IsRequired = false, EmitDefaultValue = false)]
[DefaultValue(""-1"")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public int TheIntegerProperty { get; set; }
[DataMember(Name = ""TheLongProperty"", IsRequired = false, EmitDefaultValue = false)]
[DefaultValue(""-1"")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public long TheLongProperty { get; set; }
[DataMember(Name = ""TheStringProperty"", IsRequired = false, EmitDefaultValue = false)]
[DefaultValue(""-1"")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public string TheStringProperty { get; set; }
[DataMember(Name = ""TheNullableGuidProperty"", IsRequired = false, EmitDefaultValue = false)]
public Guid? TheNullableGuidProperty { get; set; }
[DataMember(Name = ""TheUriProperty"", IsRequired = false, EmitDefaultValue = false)]
public Uri TheUriProperty { get; set; }
[DataMember(Name = ""TheBoolStringProperty"", IsRequired = false, EmitDefaultValue = false)]
public string TheBoolStringProperty { get; set; }
[DataMember(Name = ""TheStringBoolProperty"", IsRequired = false, EmitDefaultValue = false)]
public bool TheStringBoolProperty { get; set; }
[DataMember(Name = ""TheDecimalProperty"", IsRequired = false, EmitDefaultValue = false)]
[DefaultValue(""1.11111"")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public decimal TheDecimalProperty { get; set; }
[DataMember(Name = ""TheDoubleProperty"", IsRequired = false, EmitDefaultValue = false)]
[DefaultValue(""1.11111"")]
[JsonProperty(DefaultValueHandling = DefaultValueHandling.IgnoreAndPopulate)]
public double TheDoubleProperty { get; set; }
}
}"
)
};
[Theory(DisplayName = nameof(PropertyHintTypeNameTest))]
[MemberData(nameof(TestCases))]
public void PropertyHintTypeNameTest(HintTestCase testCase)
{
RunHintTestCase(testCase);
}
}
}

Просмотреть файл

@ -425,12 +425,12 @@ namespace Microsoft.Json.Schema.ToDotNet
/// </returns>
protected override SyntaxToken[] GenerateSchemaPropertyModifiers(string propertyName)
{
PropertyModifiersHint propertyModifiersHint = HintDictionary?.GetPropertyHint<PropertyModifiersHint>(TypeName, propertyName);
PropertyHint propertyHint = HintDictionary?.GetPropertyHint<PropertyHint>(TypeName, propertyName);
IList<SyntaxToken> modifierTokens;
if (propertyModifiersHint?.Modifiers != null)
if (propertyHint?.Modifiers != null)
{
modifierTokens = propertyModifiersHint.Modifiers;
modifierTokens = propertyHint.Modifiers;
}
else
{

Просмотреть файл

@ -109,7 +109,7 @@ namespace Microsoft.Json.Schema.ToDotNet
PropertyDeclarationSyntax propDecl = SyntaxFactory.PropertyDeclaration(
info.Type,
propertyName.ToPascalCase())
.AddModifiers(GenerateSchemaPropertyModifiers(propertyName))
.AddModifiers(GenerateSchemaPropertyModifiers(info.SerializedName))
.AddAccessorListAccessors(GeneratePropertyAccessors());
AttributeSyntax[] attributes = GeneratePropertyAttributes(propertyName, info.SerializedName, info.IsRequired, info.DefaultValue, info.Type);

Просмотреть файл

@ -42,8 +42,7 @@ namespace Microsoft.Json.Schema.ToDotNet.Hints
[HintKind.DictionaryHint] = CreateDictionaryHint,
[HintKind.EnumHint] = CreateEnumHint,
[HintKind.InterfaceHint] = CreateInterfaceHint,
[HintKind.PropertyModifiersHint] = CreatePropertyModifiersHint,
[HintKind.PropertyNameHint] = CreatePropertyNameHint
[HintKind.PropertyHint] = CreatePropertyHint
});
var infoDictionary = HintInstantiationInfoDictionary.Deserialize(dictionaryText);
@ -193,35 +192,30 @@ namespace Microsoft.Json.Schema.ToDotNet.Hints
};
}
private static CodeGenHint CreatePropertyModifiersHint(JObject arguments)
private static CodeGenHint CreatePropertyHint(JObject arguments)
{
string[] modifiers = GetArrayArgument<string>(arguments, nameof(PropertyModifiersHint.Modifiers));
string[] modifiers = GetArrayArgument<string>(arguments, nameof(PropertyHint.Modifiers));
string typeName = GetArgument<string>(arguments, nameof(PropertyHint.TypeName));
string name = GetArgument<string>(arguments, nameof(PropertyHint.Name));
return new PropertyModifiersHint(modifiers);
return new PropertyHint(modifiers, typeName, name);
}
private static CodeGenHint CreatePropertyNameHint(JObject arguments)
{
string dotNetPropertyName = GetArgument<string>(arguments, nameof(PropertyNameHint.DotNetPropertyName));
return new PropertyNameHint(dotNetPropertyName);
}
private static T GetArgument<T>(JObject arguments, string dotNetPropertyName)
private static T GetArgument<T>(JObject arguments, string name)
{
return arguments == null
? default(T)
: arguments.Value<T>(dotNetPropertyName.ToCamelCase());
: arguments.Value<T>(name.ToCamelCase());
}
private static T[] GetArrayArgument<T>(JObject arguments, string dotNetPropertyName)
private static T[] GetArrayArgument<T>(JObject arguments, string name)
{
if (arguments == null)
{
return default(T[]);
}
JArray arrayValue = arguments.Value<JArray>(dotNetPropertyName.ToCamelCase());
JArray arrayValue = arguments.Value<JArray>(name.ToCamelCase());
if (arrayValue == null)
{
return default(T[]);
@ -230,9 +224,9 @@ namespace Microsoft.Json.Schema.ToDotNet.Hints
return arrayValue.Values<T>().ToArray();
}
private static IDictionary<string, string> GetObjectArgument(JObject arguments, string dotNetPropertyName)
private static IDictionary<string, string> GetObjectArgument(JObject arguments, string name)
{
JObject jObject = arguments?.Value<JObject>(dotNetPropertyName.ToCamelCase());
JObject jObject = arguments?.Value<JObject>(name.ToCamelCase());
if (jObject == null)
{
return null;

Просмотреть файл

@ -24,7 +24,6 @@ namespace Microsoft.Json.Schema.ToDotNet.Hints
DictionaryHint,
EnumHint,
InterfaceHint,
PropertyModifiersHint,
PropertyNameHint
PropertyHint
}
}

Просмотреть файл

@ -12,20 +12,27 @@ namespace Microsoft.Json.Schema.ToDotNet.Hints
{
/// <summary>
/// Represents a code generation hint that tells the code generator to declare a
/// property with the specified modifiers instead of the default <code>public</code>
/// modifier.
/// property with the specified modifiers, type and name.
/// </summary>
public class PropertyModifiersHint : CodeGenHint
public class PropertyHint : CodeGenHint
{
/// <summary>
/// Initializes a new instance of the <see cref="PropertyModifiersHint"/> class.
/// Initializes a new instance of the <see cref="PropertyHint"/> class.
/// </summary>
/// <param name="modifiers">
/// The property modifiers.
/// </param>
public PropertyModifiersHint(IEnumerable<string> modifiers)
/// <param name="typeName">
/// The type of the .NET property to generate.
/// </param>
/// <param name="name">
/// The name of the .NET property to generate.
/// </param>
public PropertyHint(IEnumerable<string> modifiers, string typeName, string name)
{
Modifiers = modifiers.Select(TokenFromModifierName).ToList();
Modifiers = modifiers?.Select(TokenFromModifierName).ToList();
TypeName = typeName;
Name = name;
}
private SyntaxToken TokenFromModifierName(string modifierName)
@ -69,5 +76,15 @@ namespace Microsoft.Json.Schema.ToDotNet.Hints
/// Gets the property modifiers.
/// </summary>
public IList<SyntaxToken> Modifiers { get; }
/// <summary>
/// Gets the type of the .NET property to generate.
/// </summary>
public string TypeName { get; }
/// <summary>
/// Gets the name of the .NET property to generate.
/// </summary>
public string Name { get; }
}
}

Просмотреть файл

@ -1,36 +0,0 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
namespace Microsoft.Json.Schema.ToDotNet.Hints
{
/// <summary>
/// Represents a code generation hint that tells the code generator to generate a
/// property with the specified name, instead of deriving the .NET property name
/// from the schema property name.
/// </summary>
public class PropertyNameHint : CodeGenHint
{
/// <summary>
/// Initializes a new instance of the <see cref="PropertyNameHint"/> class.
/// </summary>
/// <param name="dotNetPropertyName">
/// The name of the .NET property to generate.
/// </param>
public PropertyNameHint(string dotNetPropertyName)
{
if (dotNetPropertyName == null)
{
throw new ArgumentNullException(nameof(dotNetPropertyName));
}
DotNetPropertyName = dotNetPropertyName;
}
/// <summary>
/// Gets the name of the .NET property to generate.
/// </summary>
public string DotNetPropertyName { get; }
}
}

Просмотреть файл

@ -73,16 +73,16 @@ namespace Microsoft.Json.Schema.ToDotNet
const string WildCard = "*";
string hintDictionaryKey = MakeHintDictionaryKey(propertyName);
PropertyModifiersHint propertyModifiersHint = HintDictionary.GetHint<PropertyModifiersHint>(hintDictionaryKey);
if (propertyModifiersHint == null)
PropertyHint propertyHint = HintDictionary.GetHint<PropertyHint>(hintDictionaryKey);
if (propertyHint == null)
{
hintDictionaryKey = WildCard + "." + propertyName.ToPascalCase();
propertyModifiersHint = HintDictionary.GetHint<PropertyModifiersHint>(hintDictionaryKey);
propertyHint = HintDictionary.GetHint<PropertyHint>(hintDictionaryKey);
}
if (propertyModifiersHint?.Modifiers.Count > 0)
if (propertyHint?.Modifiers.Count > 0)
{
bool isPublic = propertyModifiersHint.Modifiers.Contains(SyntaxFactory.Token(SyntaxKind.PublicKeyword));
bool isPublic = propertyHint.Modifiers.Contains(SyntaxFactory.Token(SyntaxKind.PublicKeyword));
return isPublic;
}

Просмотреть файл

@ -0,0 +1,24 @@
// Copyright (c) Microsoft Corporation. All Rights Reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.Json.Schema.ToDotNet
{
/// <summary>
/// Supported C# types for <see cref="Hints.PropertyHint.TypeName"/>.
/// </summary>
public enum PropertyHintTypeName
{
Auto,
Int,
Long,
BigInteger,
Double,
Float,
Decimal,
DateTime,
Uri,
Guid,
Bool,
String
}
}

Просмотреть файл

@ -241,28 +241,37 @@ namespace Microsoft.Json.Schema.ToDotNet
HashKind scalarValueTypeHashKind =
scalarValueTypeNullable ? HashKind.ScalarReferenceType : HashKind.ScalarValueType;
if (propertySchema.IsDateTime())
var propertyHint = _hintDictionary?.GetHint<PropertyHint>(_typeName + "." + schemaPropertyName.ToPascalCase());
PropertyHintTypeName hintTypeName = PropertyHintTypeName.Auto;
if (propertyHint?.TypeName != null)
{
Enum.TryParse(propertyHint.TypeName, true, out hintTypeName);
}
if (hintTypeName == PropertyHintTypeName.DateTime || (hintTypeName == PropertyHintTypeName.Auto && propertySchema.IsDateTime()))
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakeNamedType("System.DateTime", out namespaceName);
}
else if (propertySchema.IsUri())
else if (hintTypeName == PropertyHintTypeName.Uri || (hintTypeName == PropertyHintTypeName.Auto && propertySchema.IsUri()))
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarReferenceType;
initializationKind = InitializationKind.Uri;
type = MakeNamedType("System.Uri", out namespaceName);
}
else if (propertySchema.IsUuid())
else if (hintTypeName == PropertyHintTypeName.Guid || (hintTypeName == PropertyHintTypeName.Auto && propertySchema.IsUuid()))
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = scalarValueTypeHashKind;
initializationKind = InitializationKind.SimpleAssign;
type = MakeNamedType(GuidType, out namespaceName, scalarValueTypeNullable);
}
else if (propertySchema.ShouldBeDictionary(_typeName, schemaPropertyName, _hintDictionary, out DictionaryHint dictionaryHint))
else if (hintTypeName == PropertyHintTypeName.Auto && propertySchema.ShouldBeDictionary(_typeName, schemaPropertyName, _hintDictionary, out DictionaryHint dictionaryHint))
{
comparisonKind = ComparisonKind.Dictionary;
hashKind = HashKind.Dictionary;
@ -280,14 +289,14 @@ namespace Microsoft.Json.Schema.ToDotNet
type = MakeDictionaryType(entries, schemaPropertyName, dictionaryHint, dictionaryElementSchema);
namespaceName = "System.Collections.Generic"; // For IDictionary.
}
else if ((referencedEnumTypeName = GetReferencedEnumTypeName(propertySchema)) != null)
else if (hintTypeName == PropertyHintTypeName.Auto && (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))
else if (hintTypeName == PropertyHintTypeName.Auto && propertySchema.ShouldBeEnum(_typeName, schemaPropertyName, _hintDictionary, out EnumHint enumHint))
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
@ -303,109 +312,116 @@ namespace Microsoft.Json.Schema.ToDotNet
{
SchemaType propertyType = propertySchema.SafeGetType();
switch (propertyType)
if (hintTypeName == PropertyHintTypeName.Bool || (hintTypeName == PropertyHintTypeName.Auto && propertyType == SchemaType.Boolean))
{
case SchemaType.Boolean:
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakePrimitiveType(SchemaType.Boolean);
}
else if (
hintTypeName == PropertyHintTypeName.Float ||
hintTypeName == PropertyHintTypeName.Decimal ||
hintTypeName == PropertyHintTypeName.Double ||
(hintTypeName == PropertyHintTypeName.Auto && propertyType == SchemaType.Number))
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakeProperNumberType(_generateJsonNumberAs, hintTypeName);
}
else if (
hintTypeName == PropertyHintTypeName.Int ||
hintTypeName == PropertyHintTypeName.Long ||
hintTypeName == PropertyHintTypeName.BigInteger ||
(hintTypeName == PropertyHintTypeName.Auto && propertyType == SchemaType.Integer))
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = scalarValueTypeHashKind;
initializationKind = InitializationKind.SimpleAssign;
type = MakeProperIntegerType(
schemaPropertyName,
_generateJsonIntegerAs,
hintTypeName,
propertySchema.Minimum, propertySchema.ExclusiveMinimum,
propertySchema.Maximum, propertySchema.ExclusiveMaximum,
scalarValueTypeNullable,
out namespaceName);
}
else if (hintTypeName == PropertyHintTypeName.String || (hintTypeName == PropertyHintTypeName.Auto && propertyType == SchemaType.String))
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarReferenceType;
initializationKind = InitializationKind.SimpleAssign;
type = MakePrimitiveType(SchemaType.String);
}
else if (hintTypeName == PropertyHintTypeName.Auto && propertyType == 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;
type = MakePrimitiveType(propertyType);
break;
case SchemaType.Number:
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakeProperNumberType(_generateJsonNumberAs);
break;
hashKind = HashKind.ScalarReferenceType;
}
case SchemaType.Integer:
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = scalarValueTypeHashKind;
initializationKind = InitializationKind.SimpleAssign;
type = MakeProperIntegerType(_generateJsonIntegerAs,
propertySchema.Minimum, propertySchema.ExclusiveMinimum,
propertySchema.Maximum, propertySchema.ExclusiveMaximum,
scalarValueTypeNullable,
out namespaceName);
break;
case SchemaType.String:
type = MakeObjectType(propertySchema, out namespaceName);
}
else if (hintTypeName == PropertyHintTypeName.Auto && propertyType == SchemaType.Array)
{
comparisonKind = ComparisonKind.Collection;
hashKind = HashKind.Collection;
initializationKind = InitializationKind.Collection;
namespaceName = "System.Collections.Generic"; // For IList.
type = MakeArrayType(entries, schemaPropertyName, propertySchema);
}
else if (propertyType == SchemaType.None)
{
SchemaType inferredType = InferSchemaTypeFromEnumValues(propertySchema.Enum);
if (inferredType == SchemaType.None)
{
comparisonKind = ComparisonKind.ObjectEquals;
hashKind = HashKind.ScalarReferenceType;
initializationKind = InitializationKind.None;
type = MakePrimitiveType(SchemaType.Object);
}
else if (inferredType == 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));
type = MakePrimitiveType(SchemaType.String);
}
else
{
comparisonKind = ComparisonKind.OperatorEquals;
hashKind = HashKind.ScalarValueType;
initializationKind = InitializationKind.SimpleAssign;
type = MakePrimitiveType(inferredType);
}
}
else
{
throw new ArgumentOutOfRangeException(nameof(propertySchema.Type));
}
}
var propertyNameHint = _hintDictionary?.GetHint<PropertyNameHint>(_typeName + "." + schemaPropertyName.ToPascalCase());
string dotNetPropertyName = propertyNameHint != null
? propertyNameHint.DotNetPropertyName
string name = propertyHint?.Name != null
? propertyHint.Name
: schemaPropertyName.ToPascalCase();
entries.Add(new KeyValuePair<string, PropertyInfo>(
dotNetPropertyName,
name,
new PropertyInfo(
propertySchema.Description,
schemaPropertyName,
@ -699,12 +715,25 @@ namespace Microsoft.Json.Schema.ToDotNet
return type;
}
internal TypeSyntax MakeProperIntegerType(GenerateJsonIntegerOption generateJsonIntegerAs,
internal TypeSyntax MakeProperIntegerType(
string schemaPropertyName,
GenerateJsonIntegerOption generateJsonIntegerAs,
PropertyHintTypeName hintTypeName,
double? minimum, bool? exclusiveMinimum,
double? maximum, bool? exclusiveMaximum,
bool nullable,
out string namespaceName)
{
GenerateJsonIntegerOption hintGenerateJsonIntegerAs;
if (hintTypeName != PropertyHintTypeName.Auto)
{
if (Enum.TryParse(hintTypeName.ToString(), true, out hintGenerateJsonIntegerAs))
{
generateJsonIntegerAs = hintGenerateJsonIntegerAs;
}
}
namespaceName = null;
switch (generateJsonIntegerAs)
@ -745,8 +774,18 @@ namespace Microsoft.Json.Schema.ToDotNet
}
}
internal TypeSyntax MakeProperNumberType(GenerateJsonNumberOption generateJsonNumberAs)
internal TypeSyntax MakeProperNumberType(GenerateJsonNumberOption generateJsonNumberAs, PropertyHintTypeName hintTypeName)
{
GenerateJsonNumberOption hintGenerateJsonNumberAs;
if (hintTypeName != PropertyHintTypeName.Auto)
{
if (Enum.TryParse(hintTypeName.ToString(), true, out hintGenerateJsonNumberAs))
{
generateJsonNumberAs = hintGenerateJsonNumberAs;
}
}
switch (generateJsonNumberAs)
{
case GenerateJsonNumberOption.Float:

Просмотреть файл

@ -1,6 +1,8 @@
# Microsoft Json Schema Packages
## **2.3.1** UNRELEASED
## **2.4.0** UNRELEASED
* BREAKING: Merge `HintKind`: `PropertyNameHint` and `PropertyModifiersHint` into one `PropertyHint` and change the setting `dotNetPropertyName` to `name`. [#171](https://github.com/microsoft/jschema/pull/171)
* FEATURE: Add a new setting `typeName` in `PropertyHint` to generate the specified .NET type, instead of deriving from the JSON schema. Supported values: `int`, `long`, `BigInteger`, `double`, `float`, `decimal`, `DateTime`, `Uri`, `Guid`, `bool`, `string`. [#171](https://github.com/microsoft/jschema/pull/171)
* BUG: Hint file should be consistent and use Pascal case. Fix `PropertyNameHint` not functional when Pascal case is used. [#173](https://github.com/microsoft/jschema/pull/173)
## **2.3.0** [Pointer](https://www.nuget.org/packages/Microsoft.Json.Pointer/2.3.0) | [Schema](https://www.nuget.org/packages/Microsoft.Json.Schema/2.3.0)| [Schema.ToDotNet](https://www.nuget.org/packages/Microsoft.Json.Schema.ToDotNet/2.3.0)| [Schema.Validation](https://www.nuget.org/packages/Microsoft.Json.Schema.Validation/2.3.0)