Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use IsValidJsonString, inplace of DetectIsJson - more reliable. #567

Merged
merged 2 commits into from
Nov 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions uSync.Community.Contrib/Mappers/ContentmentContentBlocks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Extensions;

using uSync.Core;
using uSync.Core.Dependency;
using uSync.Core.Mapping;

Expand Down Expand Up @@ -55,10 +55,12 @@ protected override string ProcessValues(JToken jsonValue, string editorAlias, Fu
public override IEnumerable<uSyncDependency> GetDependencies(object value, string editorAlias, DependencyFlags flags)
{
var stringValue = GetValueAs<string>(value);
if (string.IsNullOrWhiteSpace(stringValue) || !stringValue.DetectIsJson()) return Enumerable.Empty<uSyncDependency>();

var elements = JsonConvert.DeserializeObject<JArray>(stringValue);
if (elements == null || !elements.Any()) return Enumerable.Empty<uSyncDependency>();
if (stringValue.TryParseValidJsonString(out JArray elements) is false)
return Enumerable.Empty<uSyncDependency>();

if (elements == null || !elements.Any())
return Enumerable.Empty<uSyncDependency>();

var dependencies = new List<uSyncDependency>();

Expand Down
48 changes: 47 additions & 1 deletion uSync.Core/Extensions/JsonExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Net.Http.Headers;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
Expand Down Expand Up @@ -111,6 +112,51 @@ private static JToken ExpandStringValue(string stringValue)
return stringValue.GetJsonTokenValue();
}

public static bool IsValidJsonString(this string value)
{
if (string.IsNullOrWhiteSpace(value) || !value.DetectIsJson())
return false;

// umbraco thinks it's json, but is it ?

try
{
JToken.Parse(value);
return true;
}
catch {
return false;
}
}

public static bool TryParseValidJsonString(this string value, out JToken token)
=> TryParseValidJsonString<JToken>(value, out token);

/// <summary>
/// parse a value and return the JSON - only if it's valid JSON
/// </summary>
/// <remarks>
/// this value will return false for strings that don't look like json strings (e.g "hello" is false)
/// </remarks>
public static bool TryParseValidJsonString<TResult>(this string value, out TResult result)
where TResult : JToken
{
result = default;
if (string.IsNullOrWhiteSpace(value) || !value.DetectIsJson())
return false;

try
{
result = JsonConvert.DeserializeObject<TResult>(value);
return true;
}
catch
{
return false;
}
}



public static JToken GetJTokenFromObject(this object value)
{
Expand Down Expand Up @@ -140,4 +186,4 @@ public static TObject GetValueAs<TObject>(this object value)
public static bool IsAngularExpression(this string value)
=> value.StartsWith("{{") && value.EndsWith("}}");
}
}
}
14 changes: 4 additions & 10 deletions uSync.Core/Mapping/Mappers/BlockListMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
using Umbraco.Extensions;

using uSync.Core.Dependency;

Expand Down Expand Up @@ -40,26 +39,21 @@ public class BlockListMapper : SyncNestedJsonValueMapperBase, ISyncMapper
protected override JToken GetImportProperty(object value)
{
if (value == null) return null;

var stringValue = value.GetValueAs<string>();
if (stringValue == null || !stringValue.DetectIsJson())

if (stringValue.TryParseValidJsonString(out JToken tokenValue) is false)
return stringValue;

// we have to get the json, the serialize the json,
// this is to make sure we don't serizlize any formatting
// (like indented formatting). because that would
// register changes that are not there.
var b = JsonConvert.SerializeObject(value.GetJTokenFromObject(), Formatting.None);

return b;
return JsonConvert.SerializeObject(tokenValue, Formatting.None);
}


protected override JToken GetExportProperty(string value)
{
if (string.IsNullOrWhiteSpace(value) || !value.DetectIsJson()) return value;
return value.GetJsonTokenValue();
}
=> value.TryParseValidJsonString(out JToken tokenValue) is true ? tokenValue : value;

protected override string ProcessValues(JToken jsonValue, string editorAlias, Func<JObject, IContentType, JObject> GetPropertiesMethod)
{
Expand Down
71 changes: 26 additions & 45 deletions uSync.Core/Mapping/Mappers/ImagePathMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,30 +74,25 @@ public override string GetExportValue(object value, string editorAlias)
var stringValue = value?.ToString();
if (string.IsNullOrWhiteSpace(stringValue)) return stringValue;

if (stringValue.DetectIsJson())
if (stringValue.TryParseValidJsonString<JObject>(out JObject json) is false)
return StripSitePath(stringValue);

// json,
if (json != null)
{
// json,
var json = JsonConvert.DeserializeObject<JObject>(stringValue);
if (json != null)
var source = json.Value<string>("src");
if (!string.IsNullOrWhiteSpace(source))
{
var source = json.Value<string>("src");
if (!string.IsNullOrWhiteSpace(source))
{
// strip any virtual directory stuff from it.
json["src"] = StripSitePath(source);
return JsonConvert.SerializeObject(json);
}
// strip any virtual directory stuff from it.
json["src"] = StripSitePath(source);
return JsonConvert.SerializeObject(json);
}

// we always reserialize if we can, because you can get inconsitancies,
// and spaces in the json (especially from the starterkit)
// this just ensures it looks the same across sites (where possible).
return JsonConvert.SerializeObject(json, Formatting.Indented);
}


// else .
return StripSitePath(stringValue);
// we always reserialize if we can, because you can get inconsitancies,
// and spaces in the json (especially from the starterkit)
// this just ensures it looks the same across sites (where possible).
return JsonConvert.SerializeObject(json, Formatting.Indented);
}

private string StripSitePath(string filepath)
Expand Down Expand Up @@ -175,26 +170,17 @@ private string GetMediaFolderSetting(string umbracoMediaPath)
public override string GetImportValue(string value, string editorAlias)
{
var stringValue = value?.ToString();
if (string.IsNullOrWhiteSpace(stringValue)) return stringValue;
if (string.IsNullOrWhiteSpace(stringValue) is true) return stringValue;

if (stringValue.DetectIsJson())
{
// json,
var json = JsonConvert.DeserializeObject<JObject>(stringValue);
if (json != null)
{
var source = json.Value<string>("src");
if (!string.IsNullOrWhiteSpace(source))
{
// strip any virtual directory stuff from it.
json["src"] = PrePendSitePath(source);
return JsonConvert.SerializeObject(json);
}
}
}
else
{
if (stringValue.TryParseValidJsonString(out JObject json) is false)
return PrePendSitePath(stringValue);

var source = json.Value<string>("src");
if (string.IsNullOrWhiteSpace(source) is false)
{
// strip any virtual directory stuff from it.
json["src"] = PrePendSitePath(source);
return JsonConvert.SerializeObject(json);
}

return stringValue;
Expand Down Expand Up @@ -228,15 +214,10 @@ public override IEnumerable<uSyncDependency> GetDependencies(object value, strin

private string GetImagePath(string stringValue)
{
if (stringValue.DetectIsJson())
if (stringValue.TryParseValidJsonString(out JObject json))
{
// json,
var json = JsonConvert.DeserializeObject<JObject>(stringValue);
if (json != null)
{
var source = json.Value<string>("src");
if (!string.IsNullOrWhiteSpace(source)) return source;
}
var source = json.Value<string>("src");
if (string.IsNullOrWhiteSpace(source) is false) return source;
}
else
{
Expand Down
4 changes: 1 addition & 3 deletions uSync.Core/Mapping/Mappers/MacroMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,8 @@ public override IEnumerable<uSyncDependency> GetDependencies(object value, strin

private MacroValue LoadMacroValue(string macroString)
{
if (!macroString.DetectIsJson())
{
if (macroString.IsValidJsonString() is false)
return LoadFromMarkup(macroString);
}

return JsonConvert.DeserializeObject<MacroValue>(macroString);
}
Expand Down
16 changes: 5 additions & 11 deletions uSync.Core/Mapping/Mappers/MediaPicker3Mapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ public MediaPicker3Mapper(IEntityService entityService) : base(entityService)
public override string GetExportValue(object value, string editorAlias)
{
var stringValue = value?.ToString();
if (string.IsNullOrEmpty(stringValue)) return null;
if (string.IsNullOrEmpty(stringValue) is true) return null;

if (!stringValue.DetectIsJson()) return stringValue;
if (stringValue.TryParseValidJsonString(out JArray json) is false)
return stringValue;

// re-formatting the json in the picker.
//
Expand All @@ -45,29 +46,22 @@ public override string GetExportValue(object value, string editorAlias)

try
{
var json = JsonConvert.DeserializeObject<JArray>(value.ToString());
if (json != null)
return JsonConvert.SerializeObject(json, Formatting.Indented);
return JsonConvert.SerializeObject(json, Formatting.Indented);
}
catch
{
return stringValue;
}

return stringValue;

}


public override IEnumerable<uSyncDependency> GetDependencies(object value, string editorAlias, DependencyFlags flags)
{
// validate string
var stringValue = value?.ToString();
if (string.IsNullOrWhiteSpace(stringValue) || !stringValue.DetectIsJson())
if (!stringValue.TryParseValidJsonString(out JArray images) is false)
return Enumerable.Empty<uSyncDependency>();

// convert to an array.
var images = JsonConvert.DeserializeObject<JArray>(value.ToString());
if (images == null || !images.Any())
return Enumerable.Empty<uSyncDependency>();

Expand Down
3 changes: 1 addition & 2 deletions uSync.Core/Mapping/Mappers/NestedContentMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,9 @@ protected override string ProcessValues(JToken jsonValue, string editorAlias, Fu
public override IEnumerable<uSyncDependency> GetDependencies(object value, string editorAlias, DependencyFlags flags)
{
var stringValue = GetValueAs<string>(value);
if (string.IsNullOrWhiteSpace(stringValue) || !stringValue.DetectIsJson())
if (stringValue.TryParseValidJsonString(out JArray nestedJson) is false)
return Enumerable.Empty<uSyncDependency>();

var nestedJson = JsonConvert.DeserializeObject<JArray>(stringValue);
if (nestedJson == null || !nestedJson.Any())
return Enumerable.Empty<uSyncDependency>();

Expand Down
2 changes: 1 addition & 1 deletion uSync.Core/Mapping/Mappers/RepeatableValueMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public RepeatableValueMapper(IEntityService entityService)

public override string GetImportValue(string value, string editorAlias)
{
if (value.DetectIsJson())
if (value.IsValidJsonString() is true)
{
try
{
Expand Down
6 changes: 3 additions & 3 deletions uSync.Core/Mapping/SyncValueMapperCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,11 @@ public object GetImportValue(string value, string editorAlias)
/// </summary>
private string GetCleanFlatJson(string stringValue)
{
if (string.IsNullOrWhiteSpace(stringValue) || !stringValue.DetectIsJson()) return stringValue;

if (stringValue.TryParseValidJsonString(out JToken result) is false)
return stringValue;
try
{
return JsonConvert.SerializeObject(JsonConvert.DeserializeObject<JToken>(stringValue));
return JsonConvert.SerializeObject(result);
}
catch
{
Expand Down
4 changes: 2 additions & 2 deletions uSync.Core/Serialization/Serializers/ContentSerializerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Microsoft.Extensions.Logging;

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Models;
Expand Down Expand Up @@ -660,9 +661,8 @@ protected string GetExportValue(object value, IPropertyType propertyType, string
// TODO: in a perfect world, this is the best answer, don't escape any buried JSON in anything
// but there might be a couple of property value converters that don't like their nested JSON
// to not be escaped so we would need to do proper testing.
if (exportValue.DetectIsJson() && !exportValue.IsAngularExpression())
if (exportValue.TryParseValidJsonString(out JToken tokenValue) is true)
{
var tokenValue = exportValue.GetJsonTokenValue().ExpandAllJsonInToken();
return JsonConvert.SerializeObject(tokenValue, Formatting.Indented);
}
logger.LogTrace("Export Value {PropertyEditorAlias} {exportValue}", propertyType.PropertyEditorAlias, exportValue);
Expand Down
23 changes: 11 additions & 12 deletions uSync.Core/Serialization/Serializers/MediaSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ protected override SyncAttempt<IMedia> DeserializeCore(XElement node, SyncSerial
}

var saveAttempt = _mediaService.Save(item);
if (!saveAttempt.Success) {
if (!saveAttempt.Success)
{
var errors = saveAttempt.Result?.EventMessages?.FormatMessages() ?? "";
return SyncAttempt<IMedia>.Fail(item.Name, item, ChangeType.Fail, errors, saveAttempt.Exception);
}
Expand Down Expand Up @@ -194,19 +195,17 @@ private XElement SerializeFileHash(IMedia item)

private string GetFilePath(string value)
{
if (value.DetectIsJson())
{
// image cropper.
var imageCrops = JsonConvert.DeserializeObject<ImageCropperValue>(value, new JsonSerializerSettings
{
Culture = CultureInfo.InvariantCulture,
FloatParseHandling = FloatParseHandling.Decimal
});
if (value.IsValidJsonString() is false)
return value;

return imageCrops.Src;
}
// image cropper.
var imageCrops = JsonConvert.DeserializeObject<ImageCropperValue>(value, new JsonSerializerSettings
{
Culture = CultureInfo.InvariantCulture,
FloatParseHandling = FloatParseHandling.Decimal
});

return value;
return imageCrops.Src;
}

protected override Attempt<IMedia> CreateItem(string alias, ITreeEntity parent, string itemType)
Expand Down
2 changes: 1 addition & 1 deletion uSync.Core/Tracking/SyncXmlTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ private IEnumerable<uSyncChange> CompareNode(XElement target, XElement source, s

private uSyncChange Compare(string target, string source, string path, string name, bool maskValue)
{
if (source.DetectIsJson())
if (source.IsValidJsonString() is true)
{
return JsonChange(target, source, path, name, maskValue);
}
Expand Down