From ea0d641f257f28cefe65ca9846a2d3df4936f016 Mon Sep 17 00:00:00 2001 From: cankoluman Date: Thu, 24 Apr 2014 15:51:04 +0100 Subject: [PATCH] Issue #AR-1_serialization: add a numerical and date model test, - fix errors in deserializing nullable type values --- .../ArchetypeJsonConverterTest.cs | 135 ++++++++++++++++-- .../Archetype.Tests/Serialization/Models.cs | 15 +- .../Serialization/ArchetypeJsonConverter.cs | 34 ++++- 3 files changed, 168 insertions(+), 16 deletions(-) diff --git a/app/Umbraco/Archetype.Tests/Serialization/ArchetypeJsonConverterTest.cs b/app/Umbraco/Archetype.Tests/Serialization/ArchetypeJsonConverterTest.cs index ea794a8..623ac44 100644 --- a/app/Umbraco/Archetype.Tests/Serialization/ArchetypeJsonConverterTest.cs +++ b/app/Umbraco/Archetype.Tests/Serialization/ArchetypeJsonConverterTest.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Archetype.Umbraco.PropertyConverters; using Newtonsoft.Json; using NUnit.Framework; @@ -8,6 +9,41 @@ namespace Archetype.Tests.Serialization [TestFixture] public class ArchetypeJsonConverterTest { + private const string _ANNUAL_STATEMENT_JSON = +@"{ + ""fieldsets"": [ + { + ""alias"": ""annualStatement"", + ""properties"": [ + { + ""alias"": ""FiscalYearStart"", + ""value"": ""01/09/2013 00:00:00"" + }, + { + ""alias"": ""FiscalYearEnd"", + ""value"": ""31/08/2014 00:00:00"" + }, + { + ""alias"": ""DividendPaymentDate"", + ""value"": """" + }, + { + ""alias"": ""TotalShares"", + ""value"": ""345678"" + }, + { + ""alias"": ""Sales"", + ""value"": ""123456700.89"" + }, + { + ""alias"": ""Profit"", + ""value"": ""1123456.78"" + } + ] + } + ] +}"; + private const string _CONTACT_DETAILS_JSON = @"{ ""fieldsets"": [ @@ -162,10 +198,19 @@ namespace Archetype.Tests.Serialization private ContactDetails _contactDetails; private CompanyDetails _companyDetails; + private AnnualStatement _annualStatement; + private UrlPicker _webSite; [SetUp] public void SetUp() { + _webSite = new UrlPicker + { + Url = "http://test.com", + Title = "The Test Company", + OpenInNewWindow = true + }; + _contactDetails = new ContactDetails { Address = "Test Address", @@ -174,12 +219,7 @@ namespace Archetype.Tests.Serialization Mobile = "000", Name = "Test", Telephone = "111", - WebSite = new UrlPicker - { - Url = "http://test.com", - Title = "The Test Company", - OpenInNewWindow = true - } + WebSite = _webSite }; _companyDetails = new CompanyDetails @@ -187,6 +227,15 @@ namespace Archetype.Tests.Serialization Region = "Test Region", ContactDetails = _contactDetails }; + + _annualStatement = new AnnualStatement + { + FiscalYearStart = new DateTime(2013, 9, 1), + FiscalYearEnd = new DateTime(2014, 8, 31), + TotalShares = 345678, + Sales = 123456700.89, + Profit = 1123456.78m + }; } #region serialization tests @@ -199,7 +248,7 @@ namespace Archetype.Tests.Serialization } [Test] - public void RegionalModel_Fieldset_Serializes_As_Expected() + public void CompanyDetailsModel_Fieldset_Serializes_As_Expected() { var result = JsonConvert.SerializeObject(_companyDetails, Formatting.Indented); @@ -207,6 +256,15 @@ namespace Archetype.Tests.Serialization } + [Test] + public void AnnualStatementModel_Fieldset_Serializes_As_Expected() + { + var result = JsonConvert.SerializeObject(_annualStatement, Formatting.Indented); + + Assert.AreEqual(_ANNUAL_STATEMENT_JSON, result); + + } + [Test] public void NullValues_Serialize_To_Empty_String() { @@ -232,6 +290,16 @@ namespace Archetype.Tests.Serialization Assert.NotNull(archetype); } + [Test] + public void ConvertNumericAndDateModelToArchetype() + { + var converter = new ArchetypeValueConverter(); + var json = JsonConvert.SerializeObject(_annualStatement); + var archetype = (Archetype.Umbraco.Models.Archetype)converter.ConvertDataToSource(null, json, false); + + Assert.NotNull(archetype); + } + [Test] public void ConvertCompoundModelToArchetype() { @@ -313,7 +381,7 @@ namespace Archetype.Tests.Serialization #region deserialization tests [Test] - public void ConvertArchetypeToModel() + public void DeserializeModelFromArchetype() { var result = JsonConvert.DeserializeObject(_CONTACT_DETAILS_JSON); @@ -326,7 +394,54 @@ namespace Archetype.Tests.Serialization Assert.AreEqual("000", result.Mobile); Assert.AreEqual("Test", result.Name); Assert.AreEqual("111", result.Telephone); - Assert.AreEqual("http://test.com", result.WebSite); + Assert.AreEqual(_webSite.Content, result.WebSite.Content); + Assert.AreEqual(_webSite.Media, result.WebSite.Media); + Assert.AreEqual(_webSite.OpenInNewWindow, result.WebSite.OpenInNewWindow); + Assert.AreEqual(_webSite.Title, result.WebSite.Title); + Assert.AreEqual(_webSite.Url, result.WebSite.Url); + } + + [Test] + public void DeserializeNumericAndDateModelFromArchetype() + { + var result = JsonConvert.DeserializeObject(_ANNUAL_STATEMENT_JSON); + + Assert.NotNull(result); + Assert.IsInstanceOf(result); + + Assert.AreEqual(new DateTime(2013, 9, 1), result.FiscalYearStart); + Assert.AreEqual(new DateTime(2014, 8, 31), result.FiscalYearEnd); + Assert.IsNull(result.DividendPaymentDate); + Assert.AreEqual(345678, result.TotalShares); + Assert.AreEqual(123456700.89, result.Sales); + Assert.AreEqual(1123456.78m, result.Profit); + } + + [Test] + public void DeserializeNumericAndDateModel_NullableDate_HasValue_FromArchetype() + { + var annualStatement = new AnnualStatement + { + FiscalYearStart = new DateTime(2013, 9, 1), + FiscalYearEnd = new DateTime(2014, 8, 31), + DividendPaymentDate = new DateTime(2014,9,15,10,15,30), + TotalShares = 345678, + Sales = 123456700.89, + Profit = 1123456.78m + }; + + var json = JsonConvert.SerializeObject(annualStatement); + var result = JsonConvert.DeserializeObject(json); + + Assert.NotNull(result); + Assert.IsInstanceOf(result); + + Assert.AreEqual(annualStatement.FiscalYearStart, result.FiscalYearStart); + Assert.AreEqual(annualStatement.FiscalYearEnd, result.FiscalYearEnd); + Assert.AreEqual(annualStatement.DividendPaymentDate, result.DividendPaymentDate); + Assert.AreEqual(annualStatement.TotalShares, result.TotalShares); + Assert.AreEqual(annualStatement.Sales, result.Sales); + Assert.AreEqual(annualStatement.Profit, result.Profit); } [Test] diff --git a/app/Umbraco/Archetype.Tests/Serialization/Models.cs b/app/Umbraco/Archetype.Tests/Serialization/Models.cs index 95a0d6a..8a642d8 100644 --- a/app/Umbraco/Archetype.Tests/Serialization/Models.cs +++ b/app/Umbraco/Archetype.Tests/Serialization/Models.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using Archetype.Umbraco.Serialization; using Newtonsoft.Json; @@ -67,5 +68,17 @@ namespace Archetype.Tests.Serialization { } + [ArchetypeDatatype("annualStatement")] + [JsonConverter(typeof(ArchetypeJsonConverter))] + public class AnnualStatement + { + public DateTime FiscalYearStart { get; set; } + public DateTime FiscalYearEnd { get; set; } + public DateTime? DividendPaymentDate { get; set; } + public Int32 TotalShares { get; set; } + public Double Sales { get; set; } + public Decimal Profit { get; set; } + } + #endregion } diff --git a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs b/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs index c273c78..6730bd7 100644 --- a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs +++ b/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs @@ -69,10 +69,14 @@ namespace Archetype.Umbraco.Serialization foreach (var propertyInfo in properties) { var propAlias = GetJsonPropertyName(propertyInfo); - var propJToken = jToken.Single(p => p.SelectToken("alias").ToString().Equals(propAlias)); + var propJToken = jToken.SingleOrDefault(p => p.SelectToken("alias").ToString().Equals(propAlias)); + + if (propJToken == null) + continue; + var propValue = IsValueArchetypeDatatype(propertyInfo.PropertyType) ? JsonConvert.DeserializeObject(propJToken["value"].ToString(), propertyInfo.PropertyType, GetArchetypeDatatypeConverter(propertyInfo.PropertyType)) - : propJToken["value"].ToObject(propertyInfo.PropertyType); + : GetDeserializedPropertyValue(propJToken["value"], propertyInfo.PropertyType); propertyInfo.SetValue(obj, propValue); } @@ -145,7 +149,7 @@ namespace Archetype.Umbraco.Serialization IsValueArchetypeDatatype(propValue) ? new JRaw(JsonConvert.SerializeObject(propValue, GetArchetypeDatatypeConverter(propValue))) - : new JValue(GetPropertyValue(propValue)))); + : new JValue(GetSerializedPropertyValue(propValue)))); fsProperties.Add(fsProperty); } @@ -196,17 +200,37 @@ namespace Archetype.Umbraco.Serialization return (JsonConverter)Activator.CreateInstance(genericType); } - private string GetPropertyValue(object propValue) + private string GetSerializedPropertyValue(object propValue) { if (propValue == null) return String.Empty; if (propValue is bool) - return (bool)propValue ? GetPropertyValue(1) : GetPropertyValue(0); + return (bool)propValue ? GetSerializedPropertyValue(1) : GetSerializedPropertyValue(0); return String.Format("{0}", propValue); } + private object GetDeserializedPropertyValue(JToken jToken, Type type) + { + if (String.IsNullOrEmpty(jToken.ToString())) + return GetDefault(type); + + var localType = Nullable.GetUnderlyingType(type) ?? type; + + if (localType == typeof(bool)) + return jToken.ToString() == "1"; + + return localType == typeof(DateTime) + ? Convert.ToDateTime(jToken.ToString()) + : jToken.ToObject(localType); + } + + private object GetDefault(Type type) + { + return type.IsValueType ? Activator.CreateInstance(type) : null; + } + #endregion } } \ No newline at end of file