diff --git a/app/Umbraco/Archetype.Tests/Serialization/Delinter/ArchetypeJsonDelinterTest.cs b/app/Umbraco/Archetype.Tests/Serialization/Delinter/ArchetypeJsonDelinterTest.cs index 888f3d9..45712f9 100644 --- a/app/Umbraco/Archetype.Tests/Serialization/Delinter/ArchetypeJsonDelinterTest.cs +++ b/app/Umbraco/Archetype.Tests/Serialization/Delinter/ArchetypeJsonDelinterTest.cs @@ -22,6 +22,10 @@ namespace Archetype.Tests.Serialization.Delinter private const string _ESCAPED_JSON = @"{""fieldsets"":[{""properties"":[{""alias"":""slides"",""value"":""2680""}],""alias"":""slides""},{""properties"":[{""alias"":""captions"",""value"":""{\""fieldsets\"":[{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test1 test1\""}],\""alias\"":\""textstringArray\""},{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test2 test2\""}],\""alias\"":\""textstringArray\""},{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test3b test3b\""}],\""alias\"":\""textstringArray\""}]}""}],""alias"":""captions""}]}"; private const string _JSON = @"{""fieldsets"":[{""properties"":[{""alias"":""slides"",""value"":""2680""}],""alias"":""slides""},{""properties"":[{""alias"":""captions"",""value"":{""fieldsets"":[{""properties"":[{""alias"":""textstring"",""value"":""test1 test1""}],""alias"":""textstringArray""},{""properties"":[{""alias"":""textstring"",""value"":""test2 test2""}],""alias"":""textstringArray""},{""properties"":[{""alias"":""textstring"",""value"":""test3b test3b""}],""alias"":""textstringArray""}]}}],""alias"":""captions""}]}"; private const string _ESCAPED_JSON_DEEP_NESTED = @"{""fieldsets"":[{""properties"":[{""alias"":""pages"",""value"":""""},{""alias"":""captions"",""value"":""{\""fieldsets\"":[{\""properties\"":[{\""alias\"":\""captions\"",\""value\"":\""{\\\""fieldsets\\\"":[{\\\""properties\\\"":[{\\\""alias\\\"":\\\""textString\\\"",\\\""value\\\"":\\\""{\\\\\\\""fieldsets\\\\\\\"":[{\\\\\\\""properties\\\\\\\"":[{\\\\\\\""alias\\\\\\\"":\\\\\\\""textString\\\\\\\"",\\\\\\\""value\\\\\\\"":\\\\\\\""\\\\\\\""}],\\\\\\\""alias\\\\\\\"":\\\\\\\""textItem\\\\\\\""}]}\\\""}],\\\""alias\\\"":\\\""textList\\\""}]}\""}],\""alias\"":\""captions\""}]}""}],""alias"":""pages""}]}"; + private const string _ESCAPED_JSON_FROM_APP = @"{ + ""alias"": ""captions"", + ""value"": ""{\""fieldsets\"":[{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test1 test1\""}],\""alias\"":\""textstringArray\""},{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test2 test2\""}],\""alias\"":\""textstringArray\""},{\""properties\"":[{\""alias\"":\""textstring\"",\""value\"":\""test3b test3b\""}],\""alias\"":\""textstringArray\""}]}"" +}"; private SlideShow _referenceModel; private NestedClass _nestedClass; @@ -83,6 +87,30 @@ namespace Archetype.Tests.Serialization.Delinter AssertAreEqual(expectedModel, actualModel); } + [Test] + public void EscapedJson_FromApp_SerializesToModel() + { + var delintedJson = _ESCAPED_JSON_FROM_APP.DelintArchetypeJson(); + + var referenceModel = new Captions() + { + new TextString() {Text = "test1 test1"}, + new TextString() {Text = "test2 test2"}, + new TextString() {Text = "test3b test3b"} + }; + + var actualModel = ConvertArchetypeJsonToModel(delintedJson); + + Assert.IsInstanceOf(actualModel); + Assert.AreEqual(3, actualModel.Count); + + foreach (var refItem in referenceModel) + { + var index = referenceModel.IndexOf(refItem); + AssertAreEqual(refItem, actualModel.ElementAt(index)); + } + } + [Test] public void DeepNestedJson_Escapes_Correctly() { @@ -164,7 +192,7 @@ namespace Archetype.Tests.Serialization.Delinter { } - [AsArchetype("textstringArray")] /* Must have same archetype alias as list class */ + [AsArchetype("textstringArray")] /* due to hard coded string calues above, must have same archetype alias as list class */ [JsonConverter(typeof(ArchetypeJsonConverter))] public class TextString { diff --git a/app/Umbraco/Umbraco.Archetype/Extensions/Extensions.cs b/app/Umbraco/Umbraco.Archetype/Extensions/Extensions.cs index 1cade8f..652f345 100644 --- a/app/Umbraco/Umbraco.Archetype/Extensions/Extensions.cs +++ b/app/Umbraco/Umbraco.Archetype/Extensions/Extensions.cs @@ -22,14 +22,5 @@ namespace Archetype.Umbraco.Extensions { return prop.PropertyEditorAlias.InvariantEquals(Constants.PropertyEditorAlias); } - - public static string DelintArchetypeJson(this string input) - { - if (!input.DetectIsJson()) - return String.Empty; - - var delinter = new ArchetypeJsonDelinter(); - return delinter.Execute(input); - } } } diff --git a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs b/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs index 81d620f..803b7e6 100644 --- a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs +++ b/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonConverter.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Reflection; using System.Text; +using Archetype.Umbraco.Extensions; using Archetype.Umbraco.Models; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -73,7 +74,7 @@ namespace Archetype.Umbraco.Serialization foreach (var fs in jToken["fieldsets"].Where(fs => fs["alias"].ToString().Equals(GetFieldsetName(itemType)))) { var item = JsonConvert.DeserializeObject( - fs["properties"].ToString(), itemType, this); + fs["properties"].ToString().DelintArchetypeJson(), itemType, this); obj.GetType().GetMethod("Add").Invoke(obj, new[] { item }); } @@ -208,7 +209,7 @@ namespace Archetype.Umbraco.Serialization private object GetPropertyValue(PropertyInfo propertyInfo, JToken propJToken) { return IsTypeArchetypeDatatype(propertyInfo.PropertyType) - ? JsonConvert.DeserializeObject(propJToken.ToString(), propertyInfo.PropertyType, + ? JsonConvert.DeserializeObject(propJToken.ToString().DelintArchetypeJson(), propertyInfo.PropertyType, this) : IsTypeIEnumerableArchetypeDatatype(propertyInfo.PropertyType) ? JsonConvert.DeserializeObject(propJToken["value"].SelectToken("fieldsets").ToString(), propertyInfo.PropertyType, diff --git a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonDelinter.cs b/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonDelinter.cs index f452741..26607c6 100644 --- a/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonDelinter.cs +++ b/app/Umbraco/Umbraco.Archetype/Serialization/ArchetypeJsonDelinter.cs @@ -62,7 +62,7 @@ namespace Archetype.Umbraco.Serialization {DelinterStep.LabelAlias, new Regex(@"\s*\\+""(alias)\\+"":\s*")}, {DelinterStep.LabelValue, new Regex(@"\s*\\+""(value)\\+"":\s*")}, {DelinterStep.UnescapeValues, new Regex(@"""(alias|value)"":\\+""(.*?)\\+""")}, - {DelinterStep.FixNestedFieldsets, new Regex(@"""(value)"":""({""fieldsets"".+?})""")}, + {DelinterStep.FixNestedFieldsets, new Regex(@"""(value)"":\s*?""({""fieldsets"".+?})""")}, {DelinterStep.RemoveWhiteSpace, new Regex(@"\s+(?=([^""]*""[^""]*"")*[^""]*$)")} }; diff --git a/app/Umbraco/Umbraco.Archetype/Serialization/SerializationExtensions.cs b/app/Umbraco/Umbraco.Archetype/Serialization/SerializationExtensions.cs index df1cb4d..8d72842 100644 --- a/app/Umbraco/Umbraco.Archetype/Serialization/SerializationExtensions.cs +++ b/app/Umbraco/Umbraco.Archetype/Serialization/SerializationExtensions.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using Archetype.Umbraco.Extensions; using Newtonsoft.Json; using Umbraco.Core.Models; using Umbraco.Web; @@ -36,6 +37,15 @@ namespace Archetype.Umbraco.Serialization var archetypeJson = content.GetPropertyDataValue(cmsFieldAlias); return JsonConvert.DeserializeObject(archetypeJson) ?? (returnInstanceIfNull ? Activator.CreateInstance() : default(T)); - } + } + + public static string DelintArchetypeJson(this string input) + { + if (!input.DetectIsJson()) + return String.Empty; + + var delinter = new ArchetypeJsonDelinter(); + return delinter.Execute(input); + } } }