From 30359619ba2a8a489780377353b38dccfd1817d2 Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 21:21:18 -0700 Subject: [PATCH 01/13] Type serialization implemented. ButlerSerializerSettings now also allows for custom JsonSerializerSettings. Serialization Tests added (moved from JsonButlerTests). --- .../JsonButler.Tests/JsonButler.Tests.csproj | 11 +- .../JsonButler.Tests/JsonButlerTests.cs | 15 --- .../Serialization/SerializationTests.cs | 101 ++++++++++++++++++ JsonButler/JsonButler.Tests/packages.config | 1 + JsonButler/JsonButler.sln | 6 ++ .../CodeSerialization/ButlerActivator.cs | 73 +++++++++++++ .../CodeSerialization/ButlerSerializer.cs | 26 ++--- .../ButlerSerializerSettings.cs | 45 ++++---- JsonButler/JsonButler/JsonButler.csproj | 4 +- .../Utilities/CollectionUtilities.cs | 36 +++++++ .../Utilities/ReflectionUtilities.cs | 58 ++++++++++ 11 files changed, 325 insertions(+), 51 deletions(-) delete mode 100644 JsonButler/JsonButler.Tests/JsonButlerTests.cs create mode 100644 JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs create mode 100644 JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs create mode 100644 JsonButler/JsonButler/Utilities/CollectionUtilities.cs create mode 100644 JsonButler/JsonButler/Utilities/ReflectionUtilities.cs diff --git a/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj b/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj index b2e9790..d597ef5 100644 --- a/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj +++ b/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj @@ -44,16 +44,25 @@ ..\packages\MSTest.TestFramework.1.2.1\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll + - + + + + {322ECCB4-5E68-4051-AE27-43E962EA014F} + JsonButler + + diff --git a/JsonButler/JsonButler.Tests/JsonButlerTests.cs b/JsonButler/JsonButler.Tests/JsonButlerTests.cs deleted file mode 100644 index e6b4d11..0000000 --- a/JsonButler/JsonButler.Tests/JsonButlerTests.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; - - - -namespace JsonButler.Tests -{ - - [TestClass] - public class JsonButlerTests - { - [TestMethod] - public void SerializeType_CustomType_Serialized () { } - } - -} \ No newline at end of file diff --git a/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs b/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs new file mode 100644 index 0000000..749f03a --- /dev/null +++ b/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs @@ -0,0 +1,101 @@ +using System.Reflection; +using Andeart.JsonButler.CodeSerialization; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Newtonsoft.Json; + + + +namespace JsonButler.Tests.Serialization +{ + + [TestClass] + public class SerializationTests + { + [TestMethod] + public void SerializeType_SimpleCustomType_Serialized () + { + ButlerSerializerSettings serializerSettings = new ButlerSerializerSettings (Assembly.GetExecutingAssembly ()); + serializerSettings.PreferredAttributeTypesOnConstructor = new[] { typeof(JsonConstructorAttribute) }; + + JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings (); + jsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + jsonSerializerSettings.Formatting = Formatting.None; + serializerSettings.JsonSerializerSettings = jsonSerializerSettings; + + string serialized = ButlerSerializer.SerializeType (serializerSettings); + Assert.AreEqual (serialized, ButlerTestClass0.ExpectedSerialized); + } + + [TestMethod] + public void SerializeType_NoButlerSerializerSettings_Serialized () + { + string serialized = ButlerSerializer.SerializeType (); + Assert.AreEqual (serialized, ButlerTestClass0.ExpectedSerialized); + } + + [TestMethod] + public void SerializeType_NoPreferredCtorAttributes_Serialized () + { + ButlerSerializerSettings serializerSettings = new ButlerSerializerSettings (Assembly.GetExecutingAssembly ()); + + JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings (); + jsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + jsonSerializerSettings.Formatting = Formatting.None; + serializerSettings.JsonSerializerSettings = jsonSerializerSettings; + + string serialized = ButlerSerializer.SerializeType (serializerSettings); + Assert.AreEqual (serialized, ButlerTestClass0.ExpectedSerialized); + } + + [TestMethod] + public void SerializeType_NoJsonSerializerSettings_Serialized () + { + ButlerSerializerSettings serializerSettings = new ButlerSerializerSettings (Assembly.GetExecutingAssembly ()); + serializerSettings.PreferredAttributeTypesOnConstructor = new[] { typeof(JsonConstructorAttribute) }; + + string serialized = ButlerSerializer.SerializeType (serializerSettings); + Assert.AreEqual (serialized, ButlerTestClass0.ExpectedSerialized); + } + + [TestMethod] + public void SerializeType_JsonIgnoredProperty_Serialized () + { + string serialized = ButlerSerializer.SerializeType (); + Assert.AreEqual (serialized, ButlerTestClass1.ExpectedSerialized); + } + + + private class ButlerTestClass0 + { + public const string ExpectedSerialized = "{\"never\":null}"; + + [JsonProperty ("never")] + public string Never { get; private set; } + + [JsonConstructor] + public ButlerTestClass0 (string never) + { + Never = never; + } + } + + + public class ButlerTestClass1 + { + public const string ExpectedSerialized = "{\"gonna\":0}"; + + [JsonProperty ("gonna")] + public int Gonna { get; private set; } + + [JsonIgnore] + public int Give { get; private set; } + + [JsonConstructor] + public ButlerTestClass1 (int gonna) + { + Gonna = gonna; + } + } + } + +} \ No newline at end of file diff --git a/JsonButler/JsonButler.Tests/packages.config b/JsonButler/JsonButler.Tests/packages.config index 88212eb..f77a41a 100644 --- a/JsonButler/JsonButler.Tests/packages.config +++ b/JsonButler/JsonButler.Tests/packages.config @@ -2,4 +2,5 @@ + \ No newline at end of file diff --git a/JsonButler/JsonButler.sln b/JsonButler/JsonButler.sln index c7e7bee..4d72c7e 100644 --- a/JsonButler/JsonButler.sln +++ b/JsonButler/JsonButler.sln @@ -5,6 +5,8 @@ VisualStudioVersion = 15.0.27703.2042 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JsonButler", "JsonButler\JsonButler.csproj", "{322ECCB4-5E68-4051-AE27-43E962EA014F}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JsonButler.Tests", "JsonButler.Tests\JsonButler.Tests.csproj", "{C4A42D52-7CEC-41BC-BADD-3B71C49BABAB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -15,6 +17,10 @@ Global {322ECCB4-5E68-4051-AE27-43E962EA014F}.Debug|Any CPU.Build.0 = Debug|Any CPU {322ECCB4-5E68-4051-AE27-43E962EA014F}.Release|Any CPU.ActiveCfg = Release|Any CPU {322ECCB4-5E68-4051-AE27-43E962EA014F}.Release|Any CPU.Build.0 = Release|Any CPU + {C4A42D52-7CEC-41BC-BADD-3B71C49BABAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4A42D52-7CEC-41BC-BADD-3B71C49BABAB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4A42D52-7CEC-41BC-BADD-3B71C49BABAB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4A42D52-7CEC-41BC-BADD-3B71C49BABAB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs b/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs new file mode 100644 index 0000000..cc5af9e --- /dev/null +++ b/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs @@ -0,0 +1,73 @@ +using System; +using System.Reflection; +using Andeart.JsonButler.Utilities; + + + +namespace Andeart.JsonButler.CodeSerialization +{ + + public class ButlerActivator + { + public static object CreateInstance () + { + return CreateInstance (typeof(T)); + } + + public static object CreateInstance (ButlerSerializerSettings settings) + { + return CreateInstance (typeof(T), settings); + } + + public static object CreateInstance (Type type) + { + return CreateInstance (type, new ButlerSerializerSettings (type.Assembly)); + } + + public static object CreateInstance (Type type, ButlerSerializerSettings settings) + { + // Bail/simplify external objects first. + if (type.Assembly != settings.RootCallingAssembly) + { + return CreateDefaultInstance (type); + } + + ConstructorInfo constructorInfo = ReflectionUtilities.GetPreferredConstructor (type, settings.PreferredAttributeTypesOnConstructor); + if (type.IsValueType && constructorInfo == null) + { + return Activator.CreateInstance (type); + } + + return CreateInstanceWithConstructor (type, settings, constructorInfo); + } + + private static object CreateInstanceWithConstructor (Type type, ButlerSerializerSettings settings, ConstructorInfo constructorInfo) + { + ParameterInfo[] parameterInfos = constructorInfo.GetParameters (); + if (parameterInfos.Length == 0) + { + return Activator.CreateInstance (type); + } + + object[] parameterObjects = new object[parameterInfos.Length]; + for (int i = 0; i < parameterInfos.Length; i++) + { + Type parameterType = parameterInfos[i].ParameterType; + parameterObjects[i] = CreateInstance (parameterType, settings); + } + + return Activator.CreateInstance (type, parameterObjects); + } + + private static object CreateDefaultInstance (Type type) + { + if (type.IsValueType || type.IsPrimitive) + { + return Activator.CreateInstance (type); + } + + return type.IsArray ? new object[0] : null; + } + } + +} \ No newline at end of file diff --git a/JsonButler/JsonButler/CodeSerialization/ButlerSerializer.cs b/JsonButler/JsonButler/CodeSerialization/ButlerSerializer.cs index c5c5005..e17e61b 100644 --- a/JsonButler/JsonButler/CodeSerialization/ButlerSerializer.cs +++ b/JsonButler/JsonButler/CodeSerialization/ButlerSerializer.cs @@ -1,4 +1,5 @@ using System; +using Newtonsoft.Json; @@ -7,27 +8,26 @@ namespace Andeart.JsonButler.CodeSerialization public class ButlerSerializer { - public static void SerializeType () + public static string SerializeType () { - SerializeType (new ButlerSerializerSettings (typeof(T).Assembly)); + return SerializeType (typeof(T)); } - public static void SerializeType (ButlerSerializerSettings settings) { } - - private static object CreatePrimitiveObject () + public static string SerializeType (ButlerSerializerSettings settings) { - Type type = typeof(T); - return CreatePrimitiveObject (type); + return SerializeType (typeof(T), settings); } - private static object CreatePrimitiveObject (Type type) + public static string SerializeType (Type type) { - if (type.IsValueType || type.IsPrimitive) - { - return Activator.CreateInstance (type); - } + return SerializeType (type, new ButlerSerializerSettings (type.Assembly)); + } - return type.IsArray ? new object[0] : null; + public static string SerializeType (Type type, ButlerSerializerSettings settings) + { + object instance = ButlerActivator.CreateInstance (type, settings); + string instanceSerialized = JsonConvert.SerializeObject (instance, settings.JsonSerializerSettings); + return instanceSerialized; } } diff --git a/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs b/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs index f38c124..dfafe59 100644 --- a/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs +++ b/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs @@ -1,21 +1,24 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace Andeart.JsonButler.CodeSerialization -{ - public class ButlerSerializerSettings - { - public Type[] PreferredConstructorTypes { get; set; } - - public Assembly RootCallingAssembly { get; set; } - - public ButlerSerializerSettings (Assembly rootCallingAssembly) - { - RootCallingAssembly = rootCallingAssembly; - } - } -} +using System; +using System.Reflection; +using Newtonsoft.Json; + + + +namespace Andeart.JsonButler.CodeSerialization +{ + + public class ButlerSerializerSettings + { + public Assembly RootCallingAssembly { get; } + + public Type[] PreferredAttributeTypesOnConstructor { get; set; } + + public JsonSerializerSettings JsonSerializerSettings { get; set; } + + public ButlerSerializerSettings (Assembly rootCallingAssembly) + { + RootCallingAssembly = rootCallingAssembly; + } + } + +} \ No newline at end of file diff --git a/JsonButler/JsonButler/JsonButler.csproj b/JsonButler/JsonButler/JsonButler.csproj index afae27a..179dd40 100644 --- a/JsonButler/JsonButler/JsonButler.csproj +++ b/JsonButler/JsonButler/JsonButler.csproj @@ -56,7 +56,6 @@ ..\packages\System.Text.Encoding.CodePages.4.3.0\lib\net46\System.Text.Encoding.CodePages.dll - @@ -70,10 +69,13 @@ + + + diff --git a/JsonButler/JsonButler/Utilities/CollectionUtilities.cs b/JsonButler/JsonButler/Utilities/CollectionUtilities.cs new file mode 100644 index 0000000..215f16d --- /dev/null +++ b/JsonButler/JsonButler/Utilities/CollectionUtilities.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; + + + +namespace Andeart.JsonButler.Utilities +{ + + // This class only exists because this guy isn't a big fan of LINQ's performance. + // He will buy you a beer if you have a while to chat about it. + + + internal static class CollectionUtilities + { + public static bool IsNullOrEmpty (this IList list) + { + return list == null || list.Count == 0; + } + + public static bool Any (this IList list, Func predicate, out T element) + { + for (int i = 0; i < list.Count; i++) + { + if (predicate (list[i])) + { + element = list[i]; + return true; + } + } + + element = default(T); + return false; + } + } + +} \ No newline at end of file diff --git a/JsonButler/JsonButler/Utilities/ReflectionUtilities.cs b/JsonButler/JsonButler/Utilities/ReflectionUtilities.cs new file mode 100644 index 0000000..25e0e5e --- /dev/null +++ b/JsonButler/JsonButler/Utilities/ReflectionUtilities.cs @@ -0,0 +1,58 @@ +using System; +using System.Reflection; + + + +namespace Andeart.JsonButler.Utilities +{ + + internal static class ReflectionUtilities + { + public static ConstructorInfo GetPreferredConstructor (Type type, Type[] preferredAttributeTypes) + { + return GetPreferredConstructor (type.GetConstructors (), preferredAttributeTypes); + } + + public static ConstructorInfo GetPreferredConstructor (ConstructorInfo[] constructorInfos, Type[] preferredAttributeTypes) + { + if (constructorInfos.IsNullOrEmpty ()) + { + return null; + } + + if (preferredAttributeTypes.IsNullOrEmpty ()) + { + return constructorInfos[0]; + } + + if (preferredAttributeTypes.Any (IsNotAnAttribute, out Type failureType)) + { + throw new Exception($"Provided preferred-attribute-type {failureType} is not an Attribute type."); + } + + for (int i = 0; i < preferredAttributeTypes.Length; i++) + { + for (int j = 0; j < constructorInfos.Length; j++) + { + if (constructorInfos[j].GetCustomAttribute (preferredAttributeTypes[i]) != null) + { + return constructorInfos[j]; + } + } + } + + return constructorInfos[0]; + } + + private static bool IsSameOrSubclassOf (this Type derivedType, Type baseType) + { + return derivedType.IsSubclassOf (baseType) || derivedType == baseType; + } + + private static bool IsNotAnAttribute (this Type type) + { + return !type.IsSameOrSubclassOf (typeof(Attribute)); + } + } + +} \ No newline at end of file From f2bbdbfc1732af65cde431624469eec43c5f663f Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 21:22:02 -0700 Subject: [PATCH 02/13] Unused reference removed from ButlerCsFile. --- JsonButler/JsonButler/CodeGeneration/ButlerCsFile.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/JsonButler/JsonButler/CodeGeneration/ButlerCsFile.cs b/JsonButler/JsonButler/CodeGeneration/ButlerCsFile.cs index e2ec712..5c2d9d1 100644 --- a/JsonButler/JsonButler/CodeGeneration/ButlerCsFile.cs +++ b/JsonButler/JsonButler/CodeGeneration/ButlerCsFile.cs @@ -1,5 +1,4 @@ -using System.Windows.Forms; -using Andeart.JsonButler.CodeGeneration.Classes; +using Andeart.JsonButler.CodeGeneration.Classes; using Andeart.JsonButler.CodeGeneration.Namespaces; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; From b759cb70ad194acefba2647e671baf91e0b4e62f Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 21:55:01 -0700 Subject: [PATCH 03/13] ButlerSerializerSettings now prefer 'JsonConstructor' attributed constructors, by default. Attribute-prioritised constructor identification fixed. --- .../Serialization/SerializationTests.cs | 29 ++++++++++++++++++- .../CodeSerialization/ButlerActivator.cs | 3 +- .../ButlerSerializerSettings.cs | 3 ++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs b/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs index 749f03a..db82173 100644 --- a/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs +++ b/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs @@ -58,12 +58,19 @@ public void SerializeType_NoJsonSerializerSettings_Serialized () } [TestMethod] - public void SerializeType_JsonIgnoredProperty_Serialized () + public void SerializeType_JsonIgnoredProperty_PropertyIgnored () { string serialized = ButlerSerializer.SerializeType (); Assert.AreEqual (serialized, ButlerTestClass1.ExpectedSerialized); } + [TestMethod] + public void SerializeType_JsonConstructorAttribute_ConstructorRespected () + { + string serialized = ButlerSerializer.SerializeType (); + Assert.AreEqual (serialized, ButlerTestClass2.ExpectedSerialized); + } + private class ButlerTestClass0 { @@ -96,6 +103,26 @@ public ButlerTestClass1 (int gonna) Gonna = gonna; } } + + + public class ButlerTestClass2 + { + public const string ExpectedSerialized = "{\"you\":42}"; + + [JsonProperty ("you")] + public int You { get; private set; } + + public ButlerTestClass2 (float you) + { + You = 7; + } + + [JsonConstructor] + public ButlerTestClass2 (string you) + { + You = you?.Length ?? 42; + } + } } } \ No newline at end of file diff --git a/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs b/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs index cc5af9e..f1aa771 100644 --- a/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs +++ b/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs @@ -56,7 +56,8 @@ private static object CreateInstanceWithConstructor (Type type, ButlerSerializer parameterObjects[i] = CreateInstance (parameterType, settings); } - return Activator.CreateInstance (type, parameterObjects); + object instance = constructorInfo.Invoke (parameterObjects); + return instance; } private static object CreateDefaultInstance (Type type) diff --git a/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs b/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs index dfafe59..dd1586b 100644 --- a/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs +++ b/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs @@ -9,6 +9,8 @@ namespace Andeart.JsonButler.CodeSerialization public class ButlerSerializerSettings { + private static readonly Type[] _defaultPreferredAttributeTypesOnConstructor = { typeof(JsonConstructorAttribute) }; + public Assembly RootCallingAssembly { get; } public Type[] PreferredAttributeTypesOnConstructor { get; set; } @@ -18,6 +20,7 @@ public class ButlerSerializerSettings public ButlerSerializerSettings (Assembly rootCallingAssembly) { RootCallingAssembly = rootCallingAssembly; + PreferredAttributeTypesOnConstructor = _defaultPreferredAttributeTypesOnConstructor; } } From 48af55c98536660058eda0a188063475f9d29954 Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 22:23:47 -0700 Subject: [PATCH 04/13] ButlerSerializerSettings now instantiates a default JsonSerializerSettings (for ReferenceLoopHandling.Ignore, etc). --- .../JsonButler/CodeSerialization/ButlerSerializerSettings.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs b/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs index dd1586b..9d31721 100644 --- a/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs +++ b/JsonButler/JsonButler/CodeSerialization/ButlerSerializerSettings.cs @@ -21,6 +21,10 @@ public ButlerSerializerSettings (Assembly rootCallingAssembly) { RootCallingAssembly = rootCallingAssembly; PreferredAttributeTypesOnConstructor = _defaultPreferredAttributeTypesOnConstructor; + + JsonSerializerSettings = new JsonSerializerSettings (); + JsonSerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; + JsonSerializerSettings.Formatting = Formatting.None; } } From 69149c2949fea3ad0a0eb7fb6c1720d0b96cb351 Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 22:24:54 -0700 Subject: [PATCH 05/13] Array creation now correctly creates array of corresponding type. --- JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs b/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs index f1aa771..1fafb74 100644 --- a/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs +++ b/JsonButler/JsonButler/CodeSerialization/ButlerActivator.cs @@ -67,7 +67,7 @@ private static object CreateDefaultInstance (Type type) return Activator.CreateInstance (type); } - return type.IsArray ? new object[0] : null; + return type.IsArray ? Activator.CreateInstance (type, 0) : null; } } From c8848f33fa010884d9c821725dbd59553dfa4a29 Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 22:25:24 -0700 Subject: [PATCH 06/13] Test messaging updated. Test Asserts corrected. Tests updated. --- .../Serialization/SerializationTests.cs | 51 ++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs b/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs index db82173..75a28e5 100644 --- a/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs +++ b/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs @@ -23,14 +23,18 @@ public void SerializeType_SimpleCustomType_Serialized () serializerSettings.JsonSerializerSettings = jsonSerializerSettings; string serialized = ButlerSerializer.SerializeType (serializerSettings); - Assert.AreEqual (serialized, ButlerTestClass0.ExpectedSerialized); + const string expected = ButlerTestClass0.ExpectedSerialized; + string errorMessage = $"Expected: {expected}; Actual: {serialized}"; + Assert.AreEqual (expected, serialized, errorMessage); } [TestMethod] public void SerializeType_NoButlerSerializerSettings_Serialized () { string serialized = ButlerSerializer.SerializeType (); - Assert.AreEqual (serialized, ButlerTestClass0.ExpectedSerialized); + const string expected = ButlerTestClass0.ExpectedSerialized; + string errorMessage = $"Expected: {expected}; Actual: {serialized}"; + Assert.AreEqual (expected, serialized, errorMessage); } [TestMethod] @@ -44,7 +48,9 @@ public void SerializeType_NoPreferredCtorAttributes_Serialized () serializerSettings.JsonSerializerSettings = jsonSerializerSettings; string serialized = ButlerSerializer.SerializeType (serializerSettings); - Assert.AreEqual (serialized, ButlerTestClass0.ExpectedSerialized); + const string expected = ButlerTestClass0.ExpectedSerialized; + string errorMessage = $"Expected: {expected}; Actual: {serialized}"; + Assert.AreEqual (expected, serialized, errorMessage); } [TestMethod] @@ -54,21 +60,36 @@ public void SerializeType_NoJsonSerializerSettings_Serialized () serializerSettings.PreferredAttributeTypesOnConstructor = new[] { typeof(JsonConstructorAttribute) }; string serialized = ButlerSerializer.SerializeType (serializerSettings); - Assert.AreEqual (serialized, ButlerTestClass0.ExpectedSerialized); + const string expected = ButlerTestClass0.ExpectedSerialized; + string errorMessage = $"Expected: {expected}; Actual: {serialized}"; + Assert.AreEqual (expected, serialized, errorMessage); } [TestMethod] public void SerializeType_JsonIgnoredProperty_PropertyIgnored () { string serialized = ButlerSerializer.SerializeType (); - Assert.AreEqual (serialized, ButlerTestClass1.ExpectedSerialized); + const string expected = ButlerTestClass1.ExpectedSerialized; + string errorMessage = $"Expected: {expected}; Actual: {serialized}"; + Assert.AreEqual (expected, serialized, errorMessage); } [TestMethod] public void SerializeType_JsonConstructorAttribute_ConstructorRespected () { string serialized = ButlerSerializer.SerializeType (); - Assert.AreEqual (serialized, ButlerTestClass2.ExpectedSerialized); + const string expected = ButlerTestClass2.ExpectedSerialized; + string errorMessage = $"Expected: {expected}; Actual: {serialized}"; + Assert.AreEqual (expected, serialized, errorMessage); + } + + [TestMethod] + public void SerializeType_ArrayProperty_SerializedAsArray () + { + string serialized = ButlerSerializer.SerializeType (); + const string expected = ButlerTestClass3.ExpectedSerialized; + string errorMessage = $"Expected: {expected}; Actual: {serialized}"; + Assert.AreEqual (expected, serialized, errorMessage); } @@ -123,6 +144,24 @@ public ButlerTestClass2 (string you) You = you?.Length ?? 42; } } + + + public class ButlerTestClass3 + { + public const string ExpectedSerialized = "{\"up\":[],\"never\":[]}"; + + [JsonProperty ("up")] + public int[] Up { get; private set; } + + [JsonProperty ("never")] + public string[] Never { get; private set; } + + public ButlerTestClass3 (int[] up, string[] never) + { + Up = up; + Never = never; + } + } } } \ No newline at end of file From 53a93f915967ddca1c64f346776313a1defef36c Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 23:00:59 -0700 Subject: [PATCH 07/13] Simple code generation test added. --- .../Generation/GenerationTests.cs | 24 ++++ .../JsonButler.Tests/JsonButler.Tests.csproj | 14 ++ .../Properties/Resources.Designer.cs | 109 +++++++++++++++ .../Properties/Resources.resx | 127 ++++++++++++++++++ .../JsonButler.Tests/Resources/ButlerCs0.cs | 77 +++++++++++ .../Resources/ButlerJson0.json | 15 +++ ...ButlerCsFile.cs => ButlerCodeGenerator.cs} | 4 +- JsonButler/JsonButler/JsonButler.csproj | 2 +- 8 files changed, 369 insertions(+), 3 deletions(-) create mode 100644 JsonButler/JsonButler.Tests/Generation/GenerationTests.cs create mode 100644 JsonButler/JsonButler.Tests/Properties/Resources.Designer.cs create mode 100644 JsonButler/JsonButler.Tests/Properties/Resources.resx create mode 100644 JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs create mode 100644 JsonButler/JsonButler.Tests/Resources/ButlerJson0.json rename JsonButler/JsonButler/CodeGeneration/{ButlerCsFile.cs => ButlerCodeGenerator.cs} (92%) diff --git a/JsonButler/JsonButler.Tests/Generation/GenerationTests.cs b/JsonButler/JsonButler.Tests/Generation/GenerationTests.cs new file mode 100644 index 0000000..609e255 --- /dev/null +++ b/JsonButler/JsonButler.Tests/Generation/GenerationTests.cs @@ -0,0 +1,24 @@ +using Andeart.JsonButler.CodeGeneration; +using Andeart.JsonButler.Tests.Properties; +using Microsoft.VisualStudio.TestTools.UnitTesting; + + + +namespace Andeart.JsonButler.Tests.Generation +{ + + [TestClass] + public class GenerationTests + { + [TestMethod] + public void GenerateCodeFile_ComplexData_CodeGenerated () + { + string input = Resources.ButlerJson0; + string generatedCsCode = ButlerCodeGenerator.GenerateCodeFile (input); + string expected = Resources.ButlerCs0; + + Assert.AreEqual (expected, generatedCsCode, "Generated code was not correct."); + } + } + +} \ No newline at end of file diff --git a/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj b/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj index d597ef5..ef4e72d 100644 --- a/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj +++ b/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj @@ -51,11 +51,19 @@ + + + True + True + Resources.resx + + + @@ -63,6 +71,12 @@ JsonButler + + + ResXFileCodeGenerator + Resources.Designer.cs + + diff --git a/JsonButler/JsonButler.Tests/Properties/Resources.Designer.cs b/JsonButler/JsonButler.Tests/Properties/Resources.Designer.cs new file mode 100644 index 0000000..a889441 --- /dev/null +++ b/JsonButler/JsonButler.Tests/Properties/Resources.Designer.cs @@ -0,0 +1,109 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Andeart.JsonButler.Tests.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Andeart.JsonButler.Tests.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to { + /// "name": "Rick Astley", + /// "lines": [ + /// "Never gonna give you up", + /// "Never gonna let you down", + /// "Never gonna run around", + /// "And desert you" + /// ], + /// "winning_number": 42, + /// "nested_type": { + /// "super_nested_type": { + /// "id": 3.14 + /// } + /// } + ///}. + /// + internal static string ButlerCs0 { + get { + return ResourceManager.GetString("ButlerCs0", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to { + /// "name": "Rick Astley", + /// "lines": [ + /// "Never gonna give you up", + /// "Never gonna let you down", + /// "Never gonna run around", + /// "And desert you" + /// ], + /// "winning_number": 42, + /// "nested_type": { + /// "super_nested_type": { + /// "id": 3.14 + /// } + /// } + ///}. + /// + internal static string ButlerJson0 { + get { + return ResourceManager.GetString("ButlerJson0", resourceCulture); + } + } + } +} diff --git a/JsonButler/JsonButler.Tests/Properties/Resources.resx b/JsonButler/JsonButler.Tests/Properties/Resources.resx new file mode 100644 index 0000000..bdf4c34 --- /dev/null +++ b/JsonButler/JsonButler.Tests/Properties/Resources.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + ..\Resources\ButlerCs0.cs;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + + ..\Resources\ButlerJson0.json;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252 + + \ No newline at end of file diff --git a/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs b/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs new file mode 100644 index 0000000..ea8840d --- /dev/null +++ b/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs @@ -0,0 +1,77 @@ +using System; +using Newtonsoft.Json; + +namespace JsonButler.Creations +{ + class ButlerFoo + { + [JsonProperty("name")] + public string Name + { + get; + private set; + } + + [JsonProperty("lines")] + public string[] Lines + { + get; + private set; + } + + [JsonProperty("winning_number")] + public int WinningNumber + { + get; + private set; + } + + [JsonProperty("nested_type")] + public NestedType NestedType + { + get; + private set; + } + + [JsonConstructor] + ButlerFoo(string name, string[] lines, int winningNumber, NestedType nestedType) + { + Name = name; + Lines = lines; + WinningNumber = winningNumber; + NestedType = nestedType; + } + } + + class NestedType + { + [JsonProperty("super_nested_type")] + public SuperNestedType SuperNestedType + { + get; + private set; + } + + [JsonConstructor] + NestedType(SuperNestedType superNestedType) + { + SuperNestedType = superNestedType; + } + } + + class SuperNestedType + { + [JsonProperty("id")] + public float TypeId + { + get; + private set; + } + + [JsonConstructor] + SuperNestedType(float typeId) + { + TypeId = typeId; + } + } +} \ No newline at end of file diff --git a/JsonButler/JsonButler.Tests/Resources/ButlerJson0.json b/JsonButler/JsonButler.Tests/Resources/ButlerJson0.json new file mode 100644 index 0000000..7562d3a --- /dev/null +++ b/JsonButler/JsonButler.Tests/Resources/ButlerJson0.json @@ -0,0 +1,15 @@ +{ + "name": "Rick Astley", + "lines": [ + "Never gonna give you up", + "Never gonna let you down", + "Never gonna run around", + "And desert you" + ], + "winning_number": 42, + "nested_type": { + "super_nested_type": { + "id": 3.14 + } + } +} \ No newline at end of file diff --git a/JsonButler/JsonButler/CodeGeneration/ButlerCsFile.cs b/JsonButler/JsonButler/CodeGeneration/ButlerCodeGenerator.cs similarity index 92% rename from JsonButler/JsonButler/CodeGeneration/ButlerCsFile.cs rename to JsonButler/JsonButler/CodeGeneration/ButlerCodeGenerator.cs index 5c2d9d1..1577163 100644 --- a/JsonButler/JsonButler/CodeGeneration/ButlerCsFile.cs +++ b/JsonButler/JsonButler/CodeGeneration/ButlerCodeGenerator.cs @@ -10,9 +10,9 @@ namespace Andeart.JsonButler.CodeGeneration { - public class ButlerCsFile + public class ButlerCodeGenerator { - public string GenerateCodeFile (string jsonText) + public static string GenerateCodeFile (string jsonText) { CompilationUnitSyntax compileUnit = SyntaxFactory.CompilationUnit (); compileUnit = compileUnit.AddUsings (SyntaxFactory.UsingDirective (SyntaxFactory.ParseName ("System"))); diff --git a/JsonButler/JsonButler/JsonButler.csproj b/JsonButler/JsonButler/JsonButler.csproj index 179dd40..fb62ba9 100644 --- a/JsonButler/JsonButler/JsonButler.csproj +++ b/JsonButler/JsonButler/JsonButler.csproj @@ -64,7 +64,7 @@ - + From 9f6b42b868f415381ab29ef40be72cc046877a61 Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 23:46:49 -0700 Subject: [PATCH 08/13] Expected output corrected. --- JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs b/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs index ea8840d..4825da6 100644 --- a/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs +++ b/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs @@ -3,7 +3,7 @@ namespace JsonButler.Creations { - class ButlerFoo + public class ButlerFoo { [JsonProperty("name")] public string Name @@ -43,7 +43,7 @@ public NestedType NestedType } } - class NestedType + public class NestedType { [JsonProperty("super_nested_type")] public SuperNestedType SuperNestedType @@ -59,19 +59,19 @@ public SuperNestedType SuperNestedType } } - class SuperNestedType + public class SuperNestedType { [JsonProperty("id")] - public float TypeId + public float Id { get; private set; } [JsonConstructor] - SuperNestedType(float typeId) + SuperNestedType(float id) { - TypeId = typeId; + Id = id; } } } \ No newline at end of file From 65ea10020f0298516e9c19ad0cf697d958a46bb4 Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 23:47:58 -0700 Subject: [PATCH 09/13] Basic test case added for code-generation. Contains nested types and arrays. --- .../Generation/GenerationTests.cs | 7 +- .../JsonButler.Tests/JsonButler.Tests.csproj | 1 + .../Utilities/TestUtilities.cs | 87 +++++++++++++++++++ 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 JsonButler/JsonButler.Tests/Utilities/TestUtilities.cs diff --git a/JsonButler/JsonButler.Tests/Generation/GenerationTests.cs b/JsonButler/JsonButler.Tests/Generation/GenerationTests.cs index 609e255..3ac9eb5 100644 --- a/JsonButler/JsonButler.Tests/Generation/GenerationTests.cs +++ b/JsonButler/JsonButler.Tests/Generation/GenerationTests.cs @@ -1,5 +1,7 @@ -using Andeart.JsonButler.CodeGeneration; +using System; +using Andeart.JsonButler.CodeGeneration; using Andeart.JsonButler.Tests.Properties; +using Andeart.JsonButler.Tests.Utilities; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -17,7 +19,8 @@ public void GenerateCodeFile_ComplexData_CodeGenerated () string generatedCsCode = ButlerCodeGenerator.GenerateCodeFile (input); string expected = Resources.ButlerCs0; - Assert.AreEqual (expected, generatedCsCode, "Generated code was not correct."); + Tuple diff = TestUtilities.PeekAtFirstDiff (expected, generatedCsCode); + Assert.AreEqual (expected, generatedCsCode, $"\n{diff.Item1}\n{diff.Item2}"); } } diff --git a/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj b/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj index ef4e72d..3ec52ce 100644 --- a/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj +++ b/JsonButler/JsonButler.Tests/JsonButler.Tests.csproj @@ -57,6 +57,7 @@ True Resources.resx + diff --git a/JsonButler/JsonButler.Tests/Utilities/TestUtilities.cs b/JsonButler/JsonButler.Tests/Utilities/TestUtilities.cs new file mode 100644 index 0000000..f9acbf1 --- /dev/null +++ b/JsonButler/JsonButler.Tests/Utilities/TestUtilities.cs @@ -0,0 +1,87 @@ +using System; + + + +namespace Andeart.JsonButler.Tests.Utilities +{ + + internal static class TestUtilities + { + public static Tuple PeekAtFirstDiff (string source, string modified) + { + if (string.IsNullOrEmpty (source)) + { + if (string.IsNullOrEmpty (modified)) + { + return new Tuple ("No difference.", null); + } + + return new Tuple ("Source is blank. Modified contains:", modified); + } + + if (string.IsNullOrEmpty (modified)) + { + return new Tuple ("Modified is blank. Source contains:", source); + } + + // If any character is different from source, return peek at that position. + for (int i = 0; i < source.Length; i++) + { + if (source[i] != modified[i]) + { + return new Tuple ("Diff in source at:", PeekSnippetAtPosition (source, i)); + } + } + + // ...at this point, it must mean modified has all of source in it, at the correct positions. + // Check lengths. + + if (source.Length != modified.Length) + { + return new Tuple ("Diff in modified at:", PeekSnippetAtPosition (modified, source.Length)); + } + + return new Tuple ("No difference.", null); + } + + private static string PeekSnippetAtPosition (string source, int position) + { + int start = position; + int end = position; + int maxEndIndex = source.Length - 1; + + // Move start caret to nearest preceding word. If already in word, do nothing. + while (char.IsWhiteSpace (source[start]) && start > 0) + { + start--; + } + + // Continue moving start caret to start of this word. + while (!char.IsWhiteSpace (source[start]) && start > 0) + { + start--; + } + + // Move end caret to nearest following whitespace. If already in whitespace, do nothing. + while (!char.IsWhiteSpace (source[end]) && end < maxEndIndex) + { + end++; + } + + // Continue moving end caret to nearest following word. If already in word, do nothing. + while (char.IsWhiteSpace (source[end]) && end < maxEndIndex) + { + end++; + } + + // Continue moving end caret to start of this word. + while (!char.IsWhiteSpace (source[end]) && end < maxEndIndex) + { + end++; + } + + return source.Substring (start, end - start); + } + } + +} \ No newline at end of file From 41ea611798750bda58c4a1c4e55bd06023c74027 Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 23:50:10 -0700 Subject: [PATCH 10/13] Classes are now created as public by default. --- .../JsonButler/CodeGeneration/Classes/ButlerClassFactory.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/JsonButler/JsonButler/CodeGeneration/Classes/ButlerClassFactory.cs b/JsonButler/JsonButler/CodeGeneration/Classes/ButlerClassFactory.cs index 121204c..ad46217 100644 --- a/JsonButler/JsonButler/CodeGeneration/Classes/ButlerClassFactory.cs +++ b/JsonButler/JsonButler/CodeGeneration/Classes/ButlerClassFactory.cs @@ -13,6 +13,7 @@ internal class ButlerClassFactory public static ButlerClass Create (string className, string path, JToken jToken) { ButlerClass bClass = new ButlerClass (className, path); + bClass.SetAccessibility (ButlerAccessibility.Public); foreach (JToken childToken in jToken.Children ()) { From 470b4e24ba5be74a142f9de23ed86cccd3e4a0d1 Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 23:51:07 -0700 Subject: [PATCH 11/13] Generated properties now use the JProperty's name, rather than the path. --- .../CodeGeneration/Properties/ButlerPropertyFactory.cs | 6 ++++-- JsonButler/JsonButler/Utilities/JsonUtilities.cs | 3 +-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/JsonButler/JsonButler/CodeGeneration/Properties/ButlerPropertyFactory.cs b/JsonButler/JsonButler/CodeGeneration/Properties/ButlerPropertyFactory.cs index 6ad53b5..b25f0e1 100644 --- a/JsonButler/JsonButler/CodeGeneration/Properties/ButlerPropertyFactory.cs +++ b/JsonButler/JsonButler/CodeGeneration/Properties/ButlerPropertyFactory.cs @@ -23,19 +23,21 @@ public static ButlerProperty Create (JToken jToken) // Create property from type. bool requiresNewClass = JsonUtilities.GetTypeFrom (jProperty.Value, out string typeName); + string propertyId = jProperty.Name; - string propertyName = jProperty.Path.ToPascalCase (); - ButlerProperty bProperty = new ButlerProperty (propertyName, propertyId, typeName); + string propertyName = propertyId.ToPascalCase (); // Create additional type if needed. List dependencies = new List (); if (requiresNewClass) { + typeName = propertyName; ButlerClass dependency = ButlerClassFactory.Create (typeName, jProperty.Path, jProperty.Value); dependencies.Add (dependency); dependencies.AddRange (dependency.Dependencies); } + ButlerProperty bProperty = new ButlerProperty (propertyName, propertyId, typeName); bProperty.AddDependencyRange (dependencies); return bProperty; diff --git a/JsonButler/JsonButler/Utilities/JsonUtilities.cs b/JsonButler/JsonButler/Utilities/JsonUtilities.cs index 1f07e61..9eddc9e 100644 --- a/JsonButler/JsonButler/Utilities/JsonUtilities.cs +++ b/JsonButler/JsonButler/Utilities/JsonUtilities.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Andeart.CaseConversion; using Newtonsoft.Json.Linq; @@ -42,7 +41,7 @@ public static bool GetTypeFrom (JToken jToken, out string type) if (tokenType == JTokenType.Object) { - type = jToken.Path.ToPascalCase (); + // Don't bother setting the type here. Type name generated is based on owner property. return true; } From be70183977e1dd1736bd4aa3066c69905863ac1e Mon Sep 17 00:00:00 2001 From: Anurag D Date: Thu, 2 Aug 2018 23:56:50 -0700 Subject: [PATCH 12/13] Test added for property with no JsonPropertyAttribute. --- .../Serialization/SerializationTests.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs b/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs index 75a28e5..a25a50d 100644 --- a/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs +++ b/JsonButler/JsonButler.Tests/Serialization/SerializationTests.cs @@ -92,6 +92,15 @@ public void SerializeType_ArrayProperty_SerializedAsArray () Assert.AreEqual (expected, serialized, errorMessage); } + [TestMethod] + public void SerializeType_NoJsonPropertyAttribute_PropertySerialized () + { + string serialized = ButlerSerializer.SerializeType (); + const string expected = ButlerTestClass4.ExpectedSerialized; + string errorMessage = $"Expected: {expected}; Actual: {serialized}"; + Assert.AreEqual (expected, serialized, errorMessage); + } + private class ButlerTestClass0 { @@ -162,6 +171,20 @@ public ButlerTestClass3 (int[] up, string[] never) Never = never; } } + + + public class ButlerTestClass4 + { + public const string ExpectedSerialized = "{\"Gonna\":false}"; + + public bool Gonna { get; } + + [JsonConstructor] + public ButlerTestClass4 (bool gonna) + { + Gonna = gonna; + } + } } } \ No newline at end of file From bdc1cd65ad8934889a7c2fdb9c6e66d4460b9aa5 Mon Sep 17 00:00:00 2001 From: Anurag D Date: Fri, 3 Aug 2018 00:06:12 -0700 Subject: [PATCH 13/13] Minor naming update in test files (for clarity). --- .../JsonButler.Tests/Resources/ButlerCs0.cs | 22 +++++++++---------- .../Resources/ButlerJson0.json | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs b/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs index 4825da6..67904e4 100644 --- a/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs +++ b/JsonButler/JsonButler.Tests/Resources/ButlerCs0.cs @@ -26,40 +26,40 @@ public int WinningNumber private set; } - [JsonProperty("nested_type")] - public NestedType NestedType + [JsonProperty("new_type")] + public NewType NewType { get; private set; } [JsonConstructor] - ButlerFoo(string name, string[] lines, int winningNumber, NestedType nestedType) + ButlerFoo(string name, string[] lines, int winningNumber, NewType newType) { Name = name; Lines = lines; WinningNumber = winningNumber; - NestedType = nestedType; + NewType = newType; } } - public class NestedType + public class NewType { - [JsonProperty("super_nested_type")] - public SuperNestedType SuperNestedType + [JsonProperty("nested_type")] + public NestedType NestedType { get; private set; } [JsonConstructor] - NestedType(SuperNestedType superNestedType) + NewType(NestedType nestedType) { - SuperNestedType = superNestedType; + NestedType = nestedType; } } - public class SuperNestedType + public class NestedType { [JsonProperty("id")] public float Id @@ -69,7 +69,7 @@ public float Id } [JsonConstructor] - SuperNestedType(float id) + NestedType(float id) { Id = id; } diff --git a/JsonButler/JsonButler.Tests/Resources/ButlerJson0.json b/JsonButler/JsonButler.Tests/Resources/ButlerJson0.json index 7562d3a..49edf5a 100644 --- a/JsonButler/JsonButler.Tests/Resources/ButlerJson0.json +++ b/JsonButler/JsonButler.Tests/Resources/ButlerJson0.json @@ -7,8 +7,8 @@ "And desert you" ], "winning_number": 42, - "nested_type": { - "super_nested_type": { + "new_type": { + "nested_type": { "id": 3.14 } }