From 43e1855b2cb8cb823f3658b4e5e1bf284cd4a075 Mon Sep 17 00:00:00 2001 From: cankoluman Date: Mon, 28 Apr 2014 12:45:30 +0100 Subject: [PATCH] Issue #AR-1_serialization: fix regression error, added AsFieldsetAttribute to help resolve ambiguous complex models, some renaming --- .../ArchetypeJsonConverterComplexModelTest.cs | 43 +++++++++++++++- .../Serialization/JsonTestModels.cs | 23 +++++---- .../Archetype.Umbraco.csproj | 3 +- .../Serialization/ArchetypeJsonConverter.cs | 51 +++++++++++++------ ...peAttribute.cs => AsArchetypeAttribute.cs} | 4 +- .../Serialization/AsFieldsetAttribute.cs | 8 +++ 6 files changed, 102 insertions(+), 30 deletions(-) rename app/Umbraco/Umbraco.Archetype/Serialization/{ArchetypeDatatypeAttribute.cs => AsArchetypeAttribute.cs} (61%) create mode 100644 app/Umbraco/Umbraco.Archetype/Serialization/AsFieldsetAttribute.cs diff --git a/app/Umbraco/Archetype.Tests/Serialization/ArchetypeJsonConverterComplexModelTest.cs b/app/Umbraco/Archetype.Tests/Serialization/ArchetypeJsonConverterComplexModelTest.cs index 8159a41..42b13cf 100644 --- a/app/Umbraco/Archetype.Tests/Serialization/ArchetypeJsonConverterComplexModelTest.cs +++ b/app/Umbraco/Archetype.Tests/Serialization/ArchetypeJsonConverterComplexModelTest.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; +using Archetype.Umbraco.PropertyConverters; using Newtonsoft.Json; using NUnit.Framework; @@ -42,8 +43,48 @@ namespace Archetype.Tests.Serialization { var result = JsonConvert.SerializeObject(_pageDetails, Formatting.Indented); Assert.AreEqual(JsonTestStrings._PAGE_DETAILS_JSON, result); - } + } + [Test] + public void ConvertComplexModelToArchetype() + { + var converter = new ArchetypeValueConverter(); + var json = JsonConvert.SerializeObject(_pageDetails, Formatting.Indented); + var archetype = (Archetype.Umbraco.Models.Archetype)converter.ConvertDataToSource(null, json, false); + + Assert.NotNull(archetype); + } + + [Test] + public void DeserializeComplexModelFromArchetype() + { + var result = JsonConvert.DeserializeObject(JsonTestStrings._PAGE_DETAILS_JSON); + + Assert.NotNull(result); + Assert.IsInstanceOf(result); + + Assert.AreEqual("2439,2440,2441,2442,2443,2444,2445,2446,2447,2448,2449,2450,2451,2452,2453", result.Pages); + Assert.AreEqual("First Page", result.Captions.TextStringArray.ElementAt(0)); + Assert.AreEqual("Second Page", result.Captions.TextStringArray.ElementAt(1)); + Assert.AreEqual("Third Page", result.Captions.TextStringArray.ElementAt(2)); + Assert.AreEqual("Fourth Page", result.Captions.TextStringArray.ElementAt(3)); + } + + [Test] + public void SerializeThenDeserializeComplexModelFromArchetype() + { + var json = JsonConvert.SerializeObject(_pageDetails); + var result = JsonConvert.DeserializeObject(json); + + Assert.NotNull(result); + Assert.IsInstanceOf(result); + + Assert.AreEqual(_pageDetails.Pages, result.Pages); + Assert.AreEqual(_pageDetails.Captions.TextStringArray.ElementAt(0), result.Captions.TextStringArray.ElementAt(0)); + Assert.AreEqual(_pageDetails.Captions.TextStringArray.ElementAt(1), result.Captions.TextStringArray.ElementAt(1)); + Assert.AreEqual(_pageDetails.Captions.TextStringArray.ElementAt(2), result.Captions.TextStringArray.ElementAt(2)); + Assert.AreEqual(_pageDetails.Captions.TextStringArray.ElementAt(3), result.Captions.TextStringArray.ElementAt(3)); + } #endregion } diff --git a/app/Umbraco/Archetype.Tests/Serialization/JsonTestModels.cs b/app/Umbraco/Archetype.Tests/Serialization/JsonTestModels.cs index 4bc26d3..24b13dd 100644 --- a/app/Umbraco/Archetype.Tests/Serialization/JsonTestModels.cs +++ b/app/Umbraco/Archetype.Tests/Serialization/JsonTestModels.cs @@ -7,7 +7,7 @@ namespace Archetype.Tests.Serialization { #region json test Models - [ArchetypeDatatype("urlPicker")] + [AsArchetype("urlPicker")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class UrlPicker { @@ -23,7 +23,7 @@ namespace Archetype.Tests.Serialization public bool OpenInNewWindow { get; set; } } - [ArchetypeDatatype("contactDetails")] + [AsArchetype("contactDetails")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class ContactDetails { @@ -43,7 +43,7 @@ namespace Archetype.Tests.Serialization public UrlPicker WebSite { get; set; } } - [ArchetypeDatatype("companyDetails")] + [AsArchetype("companyDetails")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class CompanyDetails { @@ -53,7 +53,7 @@ namespace Archetype.Tests.Serialization public ContactDetails ContactDetails { get; set; } } - [ArchetypeDatatype("allContactDetails")] + [AsArchetype("allContactDetails")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class AllContactDetails { @@ -62,13 +62,13 @@ namespace Archetype.Tests.Serialization } - [ArchetypeDatatype("contactDetailsList")] + [AsArchetype("contactDetailsList")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class ContactDetailsList : List { } - [ArchetypeDatatype("annualStatement")] + [AsArchetype("annualStatement")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class AnnualStatement { @@ -80,7 +80,7 @@ namespace Archetype.Tests.Serialization public Decimal Profit { get; set; } } - [ArchetypeDatatype("mergerDetails")] + [AsArchetype("mergerDetails")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class MergerDetails { @@ -93,17 +93,18 @@ namespace Archetype.Tests.Serialization #region complex nested model - [ArchetypeDatatype("pages")] + [AsArchetype("pages")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class PageDetails { [JsonProperty("pages")] public string Pages { get; set; } + [AsFieldset] [JsonProperty("captions")] public Captions Captions { get; set; } } - [ArchetypeDatatype("captions")] + [AsArchetype("captions")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class Captions { @@ -111,13 +112,13 @@ namespace Archetype.Tests.Serialization public TextList TextStringArray { get; set; } } - [ArchetypeDatatype("textstringArray")] + [AsArchetype("textstringArray")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class TextList : List { } - [ArchetypeDatatype("textstringArray")] + [AsArchetype("textstringArray")] [JsonConverter(typeof(ArchetypeJsonConverter))] public class TextItem { diff --git a/app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj b/app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj index 29e1f14..cdd3a7a 100644 --- a/app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj +++ b/app/Umbraco/Umbraco.Archetype/Archetype.Umbraco.csproj @@ -241,8 +241,9 @@ - + + diff --git a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs b/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs index 7b81082..b2f1694 100644 --- a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs +++ b/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs @@ -107,23 +107,42 @@ namespace Archetype.Umbraco.Serialization if (null != models) return models; - models = GetPropertiesToSerialize(value) - .Select(pInfo => - { - if (pInfo.PropertyType.IsPrimitive || pInfo.PropertyType.IsValueType - || pInfo.PropertyType.Name.Equals(typeof(String).Name)) - { - var dynamicModel = new ExpandoObject() as IDictionary; - dynamicModel.Add(GetJsonPropertyName(pInfo), pInfo.GetValue(value)); - return dynamicModel; - } + var properties = GetPropertiesToSerialize(value).ToList(); - return pInfo.GetValue(value); - }).ToList(); + if (!PropertyLayoutHasFieldsets(properties)) + return new List() { value }; + + var dynamicModel = new ExpandoObject() as IDictionary; + + foreach (var pInfo in properties.Where(pInfo => !HasAsFieldsetAttribute(pInfo))) + { + dynamicModel.Add(GetJsonPropertyName(pInfo), pInfo.GetValue(value)); + } + + var fieldsetModels = properties.Where(HasAsFieldsetAttribute) + .Select(pInfo => pInfo.GetValue(value)); + + models = new List + { + dynamicModel, + }; + + models = ((IEnumerable)models).Concat(fieldsetModels).ToList(); return models; } + private bool PropertyLayoutHasFieldsets(IEnumerable properties) + { + return properties.Any(HasAsFieldsetAttribute); + } + + private static bool HasAsFieldsetAttribute(PropertyInfo pInfo) + { + return pInfo + .GetCustomAttributes(typeof(AsFieldsetAttribute), true).Length > 0; + } + private IEnumerable SerializeModels(IEnumerable models) { var fieldsetJson = (from object model in models where null != model select SerializeModel(model)).ToList(); @@ -136,7 +155,9 @@ namespace Archetype.Umbraco.Serialization if (value == null) return null; - var jObj = IsExpandoObject(value) ? GetJObjectFromExpandoObject(value as IDictionary) : GetJObject(value); + var jObj = IsExpandoObject(value) + ? GetJObjectFromExpandoObject(value as IDictionary) + : GetJObject(value); var fieldsetJson = new StringBuilder(); var fieldsetWriter = new StringWriter(fieldsetJson); @@ -232,7 +253,7 @@ namespace Archetype.Umbraco.Serialization private string GetFieldsetName(Type type) { var attributes = type.GetCustomAttributes(true); - var archetypeDatatypeAttribute = (ArchetypeDatatypeAttribute)attributes.FirstOrDefault(attr => attr is ArchetypeDatatypeAttribute); + var archetypeDatatypeAttribute = (AsArchetypeAttribute)attributes.FirstOrDefault(attr => attr is AsArchetypeAttribute); return archetypeDatatypeAttribute != null ? archetypeDatatypeAttribute.FieldsetName : type.Name; } @@ -245,7 +266,7 @@ namespace Archetype.Umbraco.Serialization private bool IsValueArchetypeDatatype(Type type) { - return type.GetCustomAttributes(typeof(ArchetypeDatatypeAttribute), true).Length > 0; + return type.GetCustomAttributes(typeof(AsArchetypeAttribute), true).Length > 0; } private JsonConverter GetArchetypeDatatypeConverter(object value) diff --git a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeDatatypeAttribute.cs b/app/Umbraco/Umbraco.Archetype/Serialization/AsArchetypeAttribute.cs similarity index 61% rename from app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeDatatypeAttribute.cs rename to app/Umbraco/Umbraco.Archetype/Serialization/AsArchetypeAttribute.cs index bbdacfc..800bb36 100644 --- a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeDatatypeAttribute.cs +++ b/app/Umbraco/Umbraco.Archetype/Serialization/AsArchetypeAttribute.cs @@ -2,11 +2,11 @@ namespace Archetype.Umbraco.Serialization { - public class ArchetypeDatatypeAttribute : Attribute + public class AsArchetypeAttribute : Attribute { public string FieldsetName { get; set; } - public ArchetypeDatatypeAttribute(string fieldsetname) + public AsArchetypeAttribute(string fieldsetname) { FieldsetName = fieldsetname; } diff --git a/app/Umbraco/Umbraco.Archetype/Serialization/AsFieldsetAttribute.cs b/app/Umbraco/Umbraco.Archetype/Serialization/AsFieldsetAttribute.cs new file mode 100644 index 0000000..bcee649 --- /dev/null +++ b/app/Umbraco/Umbraco.Archetype/Serialization/AsFieldsetAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace Archetype.Umbraco.Serialization +{ + public class AsFieldsetAttribute : Attribute + { + } +}