diff --git a/uSync.Core/Extensions/JsonTextExtensions.cs b/uSync.Core/Extensions/JsonTextExtensions.cs index 8f8a04129..b67e1d01c 100644 --- a/uSync.Core/Extensions/JsonTextExtensions.cs +++ b/uSync.Core/Extensions/JsonTextExtensions.cs @@ -31,6 +31,8 @@ public static class JsonTextExtensions new JsonUdiRangeConverter(), new JsonBooleanConverter(), new JsonXElementConverter(), + new JsonBlockListLayoutItemConverter(), + new JsonBlockGridLayoutItemConverter() } }; diff --git a/uSync.Core/Json/JsonBlockItemConverters.cs b/uSync.Core/Json/JsonBlockItemConverters.cs new file mode 100644 index 000000000..529b65d87 --- /dev/null +++ b/uSync.Core/Json/JsonBlockItemConverters.cs @@ -0,0 +1,78 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +using Umbraco.Cms.Core.Models.Blocks; + +namespace uSync.Core.Json; + +/// +/// in v16 the BlockLayoutItem(s) have obsolete properties that are sometimes set and sometimes not +/// this leads to false positive's when looking for changes. +/// +/// these two custom converters write those properties out as null, so they never change. causing +/// the serialized json to be consistent. +/// + +public abstract class JsonBlockItemConverterBase : JsonConverter + where T : BlockLayoutItemBase, new() +{ + public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType != JsonTokenType.StartObject) + throw new JsonException("Invalid JSON expecting start object"); + + var item = new T(); + + while (reader.Read()) + { + if (reader.TokenType == JsonTokenType.EndObject) + return item; + + if (reader.TokenType != JsonTokenType.PropertyName) + throw new JsonException("Expecting property name"); + + var propertyName = reader.GetString(); + reader.Read(); + + switch (propertyName) + { + case "contentKey": + var contentKey = reader.GetString(); + if (contentKey != null && Guid.TryParse(contentKey, out var contentGuid)) + item.ContentKey = contentGuid; + break; + case "settingsKey": + var settingsKey = reader.GetString(); + if (settingsKey != null && Guid.TryParse(settingsKey, out var settingsGuid)) + item.SettingsKey = settingsGuid; + break; + default: + // we don't care about the obsolete properties here... + break; + } + } + + throw new JsonException("Unexpected end of JSON"); + } + + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + { + // we could just not write out the obsolete properties, but they will appear as null it + // lots of people's existing exports , so we can write them out as null to keep things consistent. + writer.WriteStartObject(); + writer.WriteString("contentKey", value.ContentKey.ToString()); + writer.WriteNull("contentUdi"); + + if (value.SettingsKey.HasValue && value.SettingsKey != Guid.Empty) + writer.WriteString("settingsKey", value.SettingsKey.ToString()); + else + writer.WriteNull("settingsKey"); + + writer.WriteNull("settingsUdi"); + writer.WriteEndObject(); + } +} + +public class JsonBlockListLayoutItemConverter : JsonBlockItemConverterBase { } + +public class JsonBlockGridLayoutItemConverter : JsonBlockItemConverterBase { } diff --git a/uSync.Core/Json/XElementJsonConverter.cs b/uSync.Core/Json/XElementJsonConverter.cs index 22b2a392b..23959e33e 100644 --- a/uSync.Core/Json/XElementJsonConverter.cs +++ b/uSync.Core/Json/XElementJsonConverter.cs @@ -16,3 +16,4 @@ public override void Write(Utf8JsonWriter writer, XElement value, JsonSerializer writer.WriteStringValue(value.ToString()); } } +