Prune/remove indentation from JSON property values (#11806)
* Use Formatting.None for JSON property data in default value editor * Use Formatting.None for JSON property data in custom value editors * Use Formatting.None for JSON property data in Nested Content and Block List * Use Formatting.None for JSON property tags * Use Formatting.None for JSON configuration data * Use Formatting.None in custom JSON converter * Ensure empty tags and complex editor values are not stored * Fix NestedContentPropertyComponentTests * Do not store empty property data * Use Formatting.None and don't store configured crops (without coordinates) * Fix JSON deserialization of tags value
This commit is contained in:
@@ -68,11 +68,13 @@ namespace Umbraco.Core.Models
|
||||
switch (storageType)
|
||||
{
|
||||
case TagsStorageType.Csv:
|
||||
property.SetValue(string.Join(delimiter.ToString(), currentTags.Union(trimmedTags)), culture); // csv string
|
||||
property.SetValue(string.Join(delimiter.ToString(), currentTags.Union(trimmedTags)).NullOrWhiteSpaceAsNull(), culture); // csv string
|
||||
break;
|
||||
|
||||
case TagsStorageType.Json:
|
||||
property.SetValue(JsonConvert.SerializeObject(currentTags.Union(trimmedTags).ToArray()), culture); // json array
|
||||
var updatedTags = currentTags.Union(trimmedTags).ToArray();
|
||||
var updatedValue = updatedTags.Length == 0 ? null : JsonConvert.SerializeObject(updatedTags, Formatting.None);
|
||||
property.SetValue(updatedValue, culture); // json array
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -81,11 +83,12 @@ namespace Umbraco.Core.Models
|
||||
switch (storageType)
|
||||
{
|
||||
case TagsStorageType.Csv:
|
||||
property.SetValue(string.Join(delimiter.ToString(), trimmedTags), culture); // csv string
|
||||
property.SetValue(string.Join(delimiter.ToString(), trimmedTags).NullOrWhiteSpaceAsNull(), culture); // csv string
|
||||
break;
|
||||
|
||||
case TagsStorageType.Json:
|
||||
property.SetValue(JsonConvert.SerializeObject(trimmedTags), culture); // json array
|
||||
var updatedValue = trimmedTags.Length == 0 ? null : JsonConvert.SerializeObject(trimmedTags, Formatting.None);
|
||||
property.SetValue(updatedValue, culture); // json array
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -121,11 +124,13 @@ namespace Umbraco.Core.Models
|
||||
switch (storageType)
|
||||
{
|
||||
case TagsStorageType.Csv:
|
||||
property.SetValue(string.Join(delimiter.ToString(), currentTags.Except(trimmedTags)), culture); // csv string
|
||||
property.SetValue(string.Join(delimiter.ToString(), currentTags.Except(trimmedTags)).NullOrWhiteSpaceAsNull(), culture); // csv string
|
||||
break;
|
||||
|
||||
case TagsStorageType.Json:
|
||||
property.SetValue(JsonConvert.SerializeObject(currentTags.Except(trimmedTags).ToArray()), culture); // json array
|
||||
var updatedTags = currentTags.Except(trimmedTags).ToArray();
|
||||
var updatedValue = updatedTags.Length == 0 ? null : JsonConvert.SerializeObject(updatedTags, Formatting.None);
|
||||
property.SetValue(updatedValue, culture); // json array
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -157,7 +162,7 @@ namespace Umbraco.Core.Models
|
||||
case TagsStorageType.Json:
|
||||
try
|
||||
{
|
||||
return JsonConvert.DeserializeObject<JArray>(value).Select(x => x.ToString().Trim());
|
||||
return JsonConvert.DeserializeObject<string[]>(value).Select(x => x.Trim());
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -59,11 +61,13 @@ namespace Umbraco.Core.PropertyEditors
|
||||
foreach (var cultureVal in propVals)
|
||||
{
|
||||
// Remove keys from published value & any nested properties
|
||||
var updatedPublishedVal = _formatPropertyValue(cultureVal.PublishedValue?.ToString(), onlyMissingKeys);
|
||||
var publishedValue = cultureVal.PublishedValue is JToken jsonPublishedValue ? jsonPublishedValue.ToString(Formatting.None) : cultureVal.PublishedValue?.ToString();
|
||||
var updatedPublishedVal = _formatPropertyValue(publishedValue, onlyMissingKeys).NullOrWhiteSpaceAsNull();
|
||||
cultureVal.PublishedValue = updatedPublishedVal;
|
||||
|
||||
// Remove keys from edited/draft value & any nested properties
|
||||
var updatedEditedVal = _formatPropertyValue(cultureVal.EditedValue?.ToString(), onlyMissingKeys);
|
||||
var editedValue = cultureVal.EditedValue is JToken jsonEditedValue ? jsonEditedValue.ToString(Formatting.None) : cultureVal.EditedValue?.ToString();
|
||||
var updatedEditedVal = _formatPropertyValue(editedValue, onlyMissingKeys).NullOrWhiteSpaceAsNull();
|
||||
cultureVal.EditedValue = updatedEditedVal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,8 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// </summary>
|
||||
public static JsonSerializerSettings ConfigurationJsonSettings { get; } = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.None,
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
ContractResolver = new ConfigurationCustomContractResolver(),
|
||||
Converters = new List<JsonConverter>(new[]{new FuzzyBooleanConverter()})
|
||||
};
|
||||
|
||||
@@ -145,8 +145,18 @@ namespace Umbraco.Core.PropertyEditors
|
||||
/// <returns></returns>
|
||||
internal Attempt<object> TryConvertValueToCrlType(object value)
|
||||
{
|
||||
if (value is JValue)
|
||||
value = value.ToString();
|
||||
if (value is JToken jsonValue)
|
||||
{
|
||||
if (jsonValue is JContainer && jsonValue.HasValues == false)
|
||||
{
|
||||
// Empty JSON array/object
|
||||
value = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = jsonValue.ToString(Formatting.None);
|
||||
}
|
||||
}
|
||||
|
||||
//this is a custom check to avoid any errors, if it's a string and it's empty just make it null
|
||||
if (value is string s && string.IsNullOrWhiteSpace(s))
|
||||
@@ -187,6 +197,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
return value.TryConvertTo(valueType);
|
||||
}
|
||||
|
||||
@@ -222,6 +233,7 @@ namespace Umbraco.Core.PropertyEditors
|
||||
Current.Logger.Warn<DataValueEditor,object,ValueStorageType>("The value {EditorValue} cannot be converted to the type {StorageTypeValue}", editorValue.Value, ValueTypes.ToStorageType(ValueType));
|
||||
return null;
|
||||
}
|
||||
|
||||
return result.Result;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,10 @@ namespace Umbraco.Core.Serialization
|
||||
{
|
||||
return reader.Value;
|
||||
}
|
||||
|
||||
// Load JObject from stream
|
||||
JObject jObject = JObject.Load(reader);
|
||||
return jObject.ToString();
|
||||
return jObject.ToString(Formatting.None);
|
||||
}
|
||||
|
||||
public override bool CanConvert(Type objectType)
|
||||
|
||||
@@ -14,8 +14,7 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
private readonly JsonSerializerSettings _serializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.None,
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
};
|
||||
|
||||
private const string _contentGuid1 = "036ce82586a64dfba2d523a99ed80f58";
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Web.Compose;
|
||||
|
||||
namespace Umbraco.Tests.PropertyEditors
|
||||
@@ -13,6 +10,11 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
[TestFixture]
|
||||
public class NestedContentPropertyComponentTests
|
||||
{
|
||||
private static void AreEqualJson(string expected, string actual)
|
||||
{
|
||||
Assert.AreEqual(JToken.Parse(expected), JToken.Parse(actual));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Invalid_Json()
|
||||
{
|
||||
@@ -29,17 +31,18 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
Func<Guid> guidFactory = () => guids[guidCounter++];
|
||||
|
||||
var json = @"[
|
||||
{""key"":""04a6dba8-813c-4144-8aca-86a3f24ebf08"",""name"":""Item 1"",""ncContentTypeAlias"":""nested"",""text"":""woot""},
|
||||
{""key"":""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",""name"":""Item 2"",""ncContentTypeAlias"":""nested"",""text"":""zoot""}
|
||||
]";
|
||||
{""key"":""04a6dba8-813c-4144-8aca-86a3f24ebf08"",""name"":""Item 1"",""ncContentTypeAlias"":""nested"",""text"":""woot""},
|
||||
{""key"":""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",""name"":""Item 2"",""ncContentTypeAlias"":""nested"",""text"":""zoot""}
|
||||
]";
|
||||
|
||||
var expected = json
|
||||
.Replace("04a6dba8-813c-4144-8aca-86a3f24ebf08", guids[0].ToString())
|
||||
.Replace("d8e214d8-c5a5-4b45-9b51-4050dd47f5fa", guids[1].ToString());
|
||||
|
||||
var component = new NestedContentPropertyComponent();
|
||||
var result = component.CreateNestedContentKeys(json, false, guidFactory);
|
||||
var actual = component.CreateNestedContentKeys(json, false, guidFactory);
|
||||
|
||||
Assert.AreEqual(JsonConvert.DeserializeObject(expected).ToString(), JsonConvert.DeserializeObject(result).ToString());
|
||||
AreEqualJson(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -50,29 +53,27 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
Func<Guid> guidFactory = () => guids[guidCounter++];
|
||||
|
||||
var json = @"[{
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"": [{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""fbde4288-8382-4e13-8933-ed9c160de050"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]
|
||||
}
|
||||
]";
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"": [{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""fbde4288-8382-4e13-8933-ed9c160de050"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}]
|
||||
}]";
|
||||
|
||||
var expected = json
|
||||
.Replace("04a6dba8-813c-4144-8aca-86a3f24ebf08", guids[0].ToString())
|
||||
@@ -81,9 +82,9 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
.Replace("fbde4288-8382-4e13-8933-ed9c160de050", guids[3].ToString());
|
||||
|
||||
var component = new NestedContentPropertyComponent();
|
||||
var result = component.CreateNestedContentKeys(json, false, guidFactory);
|
||||
var actual = component.CreateNestedContentKeys(json, false, guidFactory);
|
||||
|
||||
Assert.AreEqual(JsonConvert.DeserializeObject(expected).ToString(), JsonConvert.DeserializeObject(result).ToString());
|
||||
AreEqualJson(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -95,7 +96,8 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
|
||||
// we need to ensure the escaped json is consistent with how it will be re-escaped after parsing
|
||||
// and this is how to do that, the result will also include quotes around it.
|
||||
var subJsonEscaped = JsonConvert.ToString(JsonConvert.DeserializeObject(@"[{
|
||||
var subJsonEscaped = JsonConvert.ToString(JToken.Parse(@"
|
||||
[{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
@@ -105,22 +107,20 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]").ToString());
|
||||
}]").ToString(Formatting.None));
|
||||
|
||||
var json = @"[{
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + subJsonEscaped + @"
|
||||
}
|
||||
]";
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + subJsonEscaped + @"
|
||||
}]";
|
||||
|
||||
var expected = json
|
||||
.Replace("04a6dba8-813c-4144-8aca-86a3f24ebf08", guids[0].ToString())
|
||||
@@ -129,9 +129,9 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
.Replace("fbde4288-8382-4e13-8933-ed9c160de050", guids[3].ToString());
|
||||
|
||||
var component = new NestedContentPropertyComponent();
|
||||
var result = component.CreateNestedContentKeys(json, false, guidFactory);
|
||||
var actual = component.CreateNestedContentKeys(json, false, guidFactory);
|
||||
|
||||
Assert.AreEqual(JsonConvert.DeserializeObject(expected).ToString(), JsonConvert.DeserializeObject(result).ToString());
|
||||
AreEqualJson(expected, actual);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -143,7 +143,7 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
|
||||
// we need to ensure the escaped json is consistent with how it will be re-escaped after parsing
|
||||
// and this is how to do that, the result will also include quotes around it.
|
||||
var subJsonEscaped = JsonConvert.ToString(JsonConvert.DeserializeObject(@"[{
|
||||
var subJsonEscaped = JsonConvert.ToString(JToken.Parse(@"[{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
@@ -153,79 +153,74 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]").ToString());
|
||||
}]").ToString(Formatting.None));
|
||||
|
||||
// Complex editor such as the grid
|
||||
var complexEditorJsonEscaped = @"{
|
||||
""name"": ""1 column layout"",
|
||||
""sections"": [
|
||||
{
|
||||
""grid"": ""12"",
|
||||
""rows"": [
|
||||
{
|
||||
""name"": ""Article"",
|
||||
""id"": ""b4f6f651-0de3-ef46-e66a-464f4aaa9c57"",
|
||||
""areas"": [
|
||||
{
|
||||
""grid"": ""4"",
|
||||
""controls"": [
|
||||
""name"": ""1 column layout"",
|
||||
""sections"": [
|
||||
{
|
||||
""value"": ""I am quote"",
|
||||
""editor"": {
|
||||
""alias"": ""quote"",
|
||||
""view"": ""textstring""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
},
|
||||
{
|
||||
""grid"": ""8"",
|
||||
""controls"": [
|
||||
{
|
||||
""value"": ""Header"",
|
||||
""editor"": {
|
||||
""alias"": ""headline"",
|
||||
""view"": ""textstring""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
},
|
||||
{
|
||||
""value"": " + subJsonEscaped + @",
|
||||
""editor"": {
|
||||
""alias"": ""madeUpNestedContent"",
|
||||
""view"": ""madeUpNestedContentInGrid""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}]
|
||||
}]
|
||||
}";
|
||||
|
||||
""grid"": ""12"",
|
||||
""rows"": [
|
||||
{
|
||||
""name"": ""Article"",
|
||||
""id"": ""b4f6f651-0de3-ef46-e66a-464f4aaa9c57"",
|
||||
""areas"": [
|
||||
{
|
||||
""grid"": ""4"",
|
||||
""controls"": [{
|
||||
""value"": ""I am quote"",
|
||||
""editor"": {
|
||||
""alias"": ""quote"",
|
||||
""view"": ""textstring""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
},
|
||||
{
|
||||
""grid"": ""8"",
|
||||
""controls"": [{
|
||||
""value"": ""Header"",
|
||||
""editor"": {
|
||||
""alias"": ""headline"",
|
||||
""view"": ""textstring""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
},
|
||||
{
|
||||
""value"": " + subJsonEscaped + @",
|
||||
""editor"": {
|
||||
""alias"": ""madeUpNestedContent"",
|
||||
""view"": ""madeUpNestedContentInGrid""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}]
|
||||
}]
|
||||
}";
|
||||
|
||||
var json = @"[{
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + complexEditorJsonEscaped + @"
|
||||
}
|
||||
]";
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + complexEditorJsonEscaped + @"
|
||||
}]";
|
||||
|
||||
var expected = json
|
||||
.Replace("04a6dba8-813c-4144-8aca-86a3f24ebf08", guids[0].ToString())
|
||||
@@ -234,12 +229,11 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
.Replace("fbde4288-8382-4e13-8933-ed9c160de050", guids[3].ToString());
|
||||
|
||||
var component = new NestedContentPropertyComponent();
|
||||
var result = component.CreateNestedContentKeys(json, false, guidFactory);
|
||||
var actual = component.CreateNestedContentKeys(json, false, guidFactory);
|
||||
|
||||
Assert.AreEqual(JsonConvert.DeserializeObject(expected).ToString(), JsonConvert.DeserializeObject(result).ToString());
|
||||
AreEqualJson(expected, actual);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void No_Nesting_Generates_Keys_For_Missing_Items()
|
||||
{
|
||||
@@ -248,18 +242,18 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
Func<Guid> guidFactory = () => guids[guidCounter++];
|
||||
|
||||
var json = @"[
|
||||
{""key"":""04a6dba8-813c-4144-8aca-86a3f24ebf08"",""name"":""Item 1 my key wont change"",""ncContentTypeAlias"":""nested"",""text"":""woot""},
|
||||
{""name"":""Item 2 was copied and has no key prop"",""ncContentTypeAlias"":""nested"",""text"":""zoot""}
|
||||
]";
|
||||
{""key"":""04a6dba8-813c-4144-8aca-86a3f24ebf08"",""name"":""Item 1 my key wont change"",""ncContentTypeAlias"":""nested"",""text"":""woot""},
|
||||
{""name"":""Item 2 was copied and has no key prop"",""ncContentTypeAlias"":""nested"",""text"":""zoot""}
|
||||
]";
|
||||
|
||||
var component = new NestedContentPropertyComponent();
|
||||
var result = component.CreateNestedContentKeys(json, true, guidFactory);
|
||||
|
||||
// Ensure the new GUID is put in a key into the JSON
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[0].ToString()));
|
||||
|
||||
// Ensure that the original key is NOT changed/modified & still exists
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains("04a6dba8-813c-4144-8aca-86a3f24ebf08"));
|
||||
Assert.IsTrue(result.Contains("04a6dba8-813c-4144-8aca-86a3f24ebf08"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -271,7 +265,7 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
|
||||
// we need to ensure the escaped json is consistent with how it will be re-escaped after parsing
|
||||
// and this is how to do that, the result will also include quotes around it.
|
||||
var subJsonEscaped = JsonConvert.ToString(JsonConvert.DeserializeObject(@"[{
|
||||
var subJsonEscaped = JsonConvert.ToString(JToken.Parse(@"[{
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
@@ -279,29 +273,27 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
""name"": ""Nested Item 2 was copied and has no key"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]").ToString());
|
||||
}]").ToString(Formatting.None));
|
||||
|
||||
var json = @"[{
|
||||
""name"": ""Item 1 was copied and has no key"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + subJsonEscaped + @"
|
||||
}
|
||||
]";
|
||||
""name"": ""Item 1 was copied and has no key"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""key"": ""d8e214d8-c5a5-4b45-9b51-4050dd47f5fa"",
|
||||
""name"": ""Item 2"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + subJsonEscaped + @"
|
||||
}]";
|
||||
|
||||
var component = new NestedContentPropertyComponent();
|
||||
var result = component.CreateNestedContentKeys(json, true, guidFactory);
|
||||
|
||||
// Ensure the new GUID is put in a key into the JSON for each item
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[1].ToString()));
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[2].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[1].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[2].ToString()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -313,7 +305,7 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
|
||||
// we need to ensure the escaped json is consistent with how it will be re-escaped after parsing
|
||||
// and this is how to do that, the result will also include quotes around it.
|
||||
var subJsonEscaped = JsonConvert.ToString(JsonConvert.DeserializeObject(@"[{
|
||||
var subJsonEscaped = JsonConvert.ToString(JToken.Parse(@"[{
|
||||
""key"": ""dccf550c-3a05-469e-95e1-a8f560f788c2"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
@@ -322,85 +314,80 @@ namespace Umbraco.Tests.PropertyEditors
|
||||
""name"": ""Nested Item 2 was copied and has no key"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""zoot""
|
||||
}
|
||||
]").ToString());
|
||||
}]").ToString(Formatting.None));
|
||||
|
||||
// Complex editor such as the grid
|
||||
var complexEditorJsonEscaped = @"{
|
||||
""name"": ""1 column layout"",
|
||||
""sections"": [
|
||||
{
|
||||
""grid"": ""12"",
|
||||
""rows"": [
|
||||
{
|
||||
""name"": ""Article"",
|
||||
""id"": ""b4f6f651-0de3-ef46-e66a-464f4aaa9c57"",
|
||||
""areas"": [
|
||||
{
|
||||
""grid"": ""4"",
|
||||
""controls"": [
|
||||
""name"": ""1 column layout"",
|
||||
""sections"": [
|
||||
{
|
||||
""value"": ""I am quote"",
|
||||
""editor"": {
|
||||
""alias"": ""quote"",
|
||||
""view"": ""textstring""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
},
|
||||
{
|
||||
""grid"": ""8"",
|
||||
""controls"": [
|
||||
{
|
||||
""value"": ""Header"",
|
||||
""editor"": {
|
||||
""alias"": ""headline"",
|
||||
""view"": ""textstring""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
},
|
||||
{
|
||||
""value"": " + subJsonEscaped + @",
|
||||
""editor"": {
|
||||
""alias"": ""madeUpNestedContent"",
|
||||
""view"": ""madeUpNestedContentInGrid""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}]
|
||||
}]
|
||||
}";
|
||||
|
||||
""grid"": ""12"",
|
||||
""rows"": [
|
||||
{
|
||||
""name"": ""Article"",
|
||||
""id"": ""b4f6f651-0de3-ef46-e66a-464f4aaa9c57"",
|
||||
""areas"": [
|
||||
{
|
||||
""grid"": ""4"",
|
||||
""controls"": [{
|
||||
""value"": ""I am quote"",
|
||||
""editor"": {
|
||||
""alias"": ""quote"",
|
||||
""view"": ""textstring""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
},
|
||||
{
|
||||
""grid"": ""8"",
|
||||
""controls"": [{
|
||||
""value"": ""Header"",
|
||||
""editor"": {
|
||||
""alias"": ""headline"",
|
||||
""view"": ""textstring""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
},
|
||||
{
|
||||
""value"": " + subJsonEscaped + @",
|
||||
""editor"": {
|
||||
""alias"": ""madeUpNestedContent"",
|
||||
""view"": ""madeUpNestedContentInGrid""
|
||||
},
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}],
|
||||
""styles"": null,
|
||||
""config"": null
|
||||
}]
|
||||
}]
|
||||
}";
|
||||
|
||||
var json = @"[{
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""name"": ""Item 2 was copied and has no key"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + complexEditorJsonEscaped + @"
|
||||
}
|
||||
]";
|
||||
""key"": ""04a6dba8-813c-4144-8aca-86a3f24ebf08"",
|
||||
""name"": ""Item 1"",
|
||||
""ncContentTypeAlias"": ""text"",
|
||||
""text"": ""woot""
|
||||
}, {
|
||||
""name"": ""Item 2 was copied and has no key"",
|
||||
""ncContentTypeAlias"": ""list"",
|
||||
""text"": ""zoot"",
|
||||
""subItems"":" + complexEditorJsonEscaped + @"
|
||||
}]";
|
||||
|
||||
var component = new NestedContentPropertyComponent();
|
||||
var result = component.CreateNestedContentKeys(json, true, guidFactory);
|
||||
|
||||
// Ensure the new GUID is put in a key into the JSON for each item
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(JsonConvert.DeserializeObject(result).ToString().Contains(guids[1].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[0].ToString()));
|
||||
Assert.IsTrue(result.Contains(guids[1].ToString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Umbraco.Web.Compose
|
||||
|
||||
UpdateBlockListRecursively(blockListValue, createGuid);
|
||||
|
||||
return JsonConvert.SerializeObject(blockListValue.BlockValue);
|
||||
return JsonConvert.SerializeObject(blockListValue.BlockValue, Formatting.None);
|
||||
}
|
||||
|
||||
private void UpdateBlockListRecursively(BlockEditorData blockListData, Func<Guid> createGuid)
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Composing;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Services.Implement;
|
||||
using Umbraco.Web.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Web.Compose
|
||||
@@ -47,7 +43,7 @@ namespace Umbraco.Web.Compose
|
||||
|
||||
UpdateNestedContentKeysRecursively(complexEditorValue, onlyMissingKeys, createGuid);
|
||||
|
||||
return complexEditorValue.ToString();
|
||||
return complexEditorValue.ToString(Formatting.None);
|
||||
}
|
||||
|
||||
private void UpdateNestedContentKeysRecursively(JToken json, bool onlyMissingKeys, Func<Guid> createGuid)
|
||||
@@ -80,7 +76,7 @@ namespace Umbraco.Web.Compose
|
||||
var parsed = JToken.Parse(propVal);
|
||||
UpdateNestedContentKeysRecursively(parsed, onlyMissingKeys, createGuid);
|
||||
// set the value to the updated one
|
||||
prop.Value = parsed.ToString();
|
||||
prop.Value = parsed.ToString(Formatting.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
MapBlockItemData(blockEditorData.BlockValue.SettingsData);
|
||||
|
||||
// return json
|
||||
return JsonConvert.SerializeObject(blockEditorData.BlockValue);
|
||||
return JsonConvert.SerializeObject(blockEditorData.BlockValue, Formatting.None);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
if (id >= nextId) nextId = id + 1;
|
||||
|
||||
var label = item.Property("label")?.Value?.Value<string>();
|
||||
value = JsonConvert.SerializeObject(new { value, label });
|
||||
value = JsonConvert.SerializeObject(new { value, label }, Formatting.None);
|
||||
|
||||
output.Items.Add(new ValueListConfiguration.ValueListItem { Id = id, Value = value });
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
}
|
||||
|
||||
// Convert back to raw JSON for persisting
|
||||
return JsonConvert.SerializeObject(grid);
|
||||
return JsonConvert.SerializeObject(grid, Formatting.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Media;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using Umbraco.Core.PropertyEditors.ValueConverters;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Media;
|
||||
|
||||
@@ -170,7 +168,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
var sourcePath = _mediaFileSystem.GetRelativePath(src);
|
||||
var copyPath = _mediaFileSystem.CopyFile(args.Copy, property.PropertyType, sourcePath);
|
||||
jo["src"] = _mediaFileSystem.GetUrl(copyPath);
|
||||
args.Copy.SetValue(property.Alias, jo.ToString(), propertyValue.Culture, propertyValue.Segment);
|
||||
args.Copy.SetValue(property.Alias, jo.ToString(Formatting.None), propertyValue.Culture, propertyValue.Segment);
|
||||
isUpdated = true;
|
||||
}
|
||||
}
|
||||
@@ -241,17 +239,12 @@ namespace Umbraco.Web.PropertyEditors
|
||||
// it can happen when an image is uploaded via the folder browser, in which case
|
||||
// the property value will be the file source eg '/media/23454/hello.jpg' and we
|
||||
// are fixing that anomaly here - does not make any sense at all but... bah...
|
||||
|
||||
var dt = _dataTypeService.GetDataType(property.PropertyType.DataTypeId);
|
||||
var config = dt?.ConfigurationAs<ImageCropperConfiguration>();
|
||||
src = svalue;
|
||||
var json = new
|
||||
{
|
||||
src = svalue,
|
||||
crops = config == null ? Array.Empty<ImageCropperConfiguration.Crop>() : config.Crops
|
||||
};
|
||||
|
||||
property.SetValue(JsonConvert.SerializeObject(json), pvalue.Culture, pvalue.Segment);
|
||||
property.SetValue(JsonConvert.SerializeObject(new
|
||||
{
|
||||
src = svalue
|
||||
}, Formatting.None), pvalue.Culture, pvalue.Segment);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -190,6 +190,10 @@ namespace Umbraco.Web.PropertyEditors
|
||||
{
|
||||
src = val,
|
||||
crops = crops
|
||||
}, new JsonSerializerSettings()
|
||||
{
|
||||
Formatting = Formatting.None,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,22 +123,26 @@ namespace Umbraco.Web.PropertyEditors
|
||||
|
||||
private static readonly JsonSerializerSettings LinkDisplayJsonSerializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.None,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
};
|
||||
|
||||
public override object FromEditor(ContentPropertyData editorValue, object currentValue)
|
||||
{
|
||||
var value = editorValue.Value?.ToString();
|
||||
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
return string.Empty;
|
||||
return null;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var links = JsonConvert.DeserializeObject<List<LinkDisplay>>(value);
|
||||
if (links.Count == 0)
|
||||
return null;
|
||||
|
||||
return JsonConvert.SerializeObject(
|
||||
from link in JsonConvert.DeserializeObject<List<LinkDisplay>>(value)
|
||||
from link in links
|
||||
select new MultiUrlPickerValueEditor.LinkDto
|
||||
{
|
||||
Name = link.Name,
|
||||
@@ -146,8 +150,8 @@ namespace Umbraco.Web.PropertyEditors
|
||||
Target = link.Target,
|
||||
Udi = link.Udi,
|
||||
Url = link.Udi == null ? link.Url : null, // only save the URL for external links
|
||||
}, LinkDisplayJsonSerializerSettings
|
||||
);
|
||||
},
|
||||
LinkDisplayJsonSerializerSettings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
public override object FromEditor(ContentPropertyData editorValue, object currentValue)
|
||||
{
|
||||
var asArray = editorValue.Value as JArray;
|
||||
if (asArray == null)
|
||||
if (asArray == null || asArray.HasValues == false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -49,14 +49,18 @@ namespace Umbraco.Web.PropertyEditors
|
||||
public override object FromEditor(Core.Models.Editors.ContentPropertyData editorValue, object currentValue)
|
||||
{
|
||||
var json = editorValue.Value as JArray;
|
||||
if (json == null)
|
||||
if (json == null || json.HasValues == false)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var values = json.Select(item => item.Value<string>()).ToArray();
|
||||
if (values.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(values);
|
||||
return JsonConvert.SerializeObject(values, Formatting.None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
var rows = _nestedContentValues.GetPropertyValues(propertyValue);
|
||||
|
||||
if (rows.Count == 0)
|
||||
return string.Empty;
|
||||
return null;
|
||||
|
||||
foreach (var row in rows.ToList())
|
||||
{
|
||||
@@ -134,7 +134,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
}
|
||||
}
|
||||
|
||||
return JsonConvert.SerializeObject(rows).ToXmlString<string>();
|
||||
return JsonConvert.SerializeObject(rows, Formatting.None).ToXmlString<string>();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -229,7 +229,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
var rows = _nestedContentValues.GetPropertyValues(editorValue.Value);
|
||||
|
||||
if (rows.Count == 0)
|
||||
return string.Empty;
|
||||
return null;
|
||||
|
||||
foreach (var row in rows.ToList())
|
||||
{
|
||||
@@ -254,8 +254,9 @@ namespace Umbraco.Web.PropertyEditors
|
||||
}
|
||||
|
||||
// return json
|
||||
return JsonConvert.SerializeObject(rows);
|
||||
return JsonConvert.SerializeObject(rows, Formatting.None);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public IEnumerable<UmbracoEntityReference> GetReferences(object value)
|
||||
|
||||
@@ -142,7 +142,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
var editorValueWithMediaUrlsRemoved = _imageSourceParser.RemoveImageSources(parseAndSavedTempImages);
|
||||
var parsed = MacroTagParser.FormatRichTextContentForPersistence(editorValueWithMediaUrlsRemoved);
|
||||
|
||||
return parsed;
|
||||
return parsed.NullOrWhiteSpaceAsNull();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
|
||||
if (editorValue.Value is JArray json)
|
||||
{
|
||||
return json.Select(x => x.Value<string>());
|
||||
return json.HasValues ? json.Select(x => x.Value<string>()) : null;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(value) == false)
|
||||
|
||||
Reference in New Issue
Block a user