Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions uSync.Core/Extensions/JsonTextExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -520,4 +520,15 @@ public static bool IsJsonEqual(this object currentObject, object newObject)

#endregion

#region Type Checks

/// <summary>
/// checks if the value is a non-string JSON value (array, object, number, boolean).
/// </summary>
public static bool IsNonStringJsonValue(this object? value)
=> value is JsonElement { ValueKind: not JsonValueKind.String and not JsonValueKind.Undefined }
|| value is JsonArray or JsonObject;

#endregion

}
23 changes: 23 additions & 0 deletions uSync.Core/Mapping/Mappers/SingleBlockMapper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.Extensions.Logging;

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

namespace uSync.Core.Mapping.Mappers;

internal class SingleBlockMapper : SyncBlockMapperBase<SingleBlockValue>, ISyncMapper
{
public override string Name => "NuBlock Single Block mapper";

public override string[] Editors => [Constants.PropertyEditors.Aliases.SingleBlock];

public SingleBlockMapper(
IEntityService entityService,
IContentTypeService contentTypeService,
Lazy<SyncValueMapperCollection> mapperCollection,
ILogger<SingleBlockMapper> logger)
: base(entityService, contentTypeService, mapperCollection, logger)
{
}
}
13 changes: 12 additions & 1 deletion uSync.Core/Mapping/SyncBlockMapperBase.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Logging;

using System.Collections;
using System.Text.Json;
using System.Text.Json.Nodes;

using Umbraco.Cms.Core;
Expand Down Expand Up @@ -61,7 +62,17 @@ public SyncBlockMapperBase(
_logger.LogDebug("Importing block value for {PropertyEditorAlias} {valueType}", propertyType.PropertyEditorAlias, value?.GetType().Name ?? "blank");

var importString = SyncBlockMapperBase<TBlockValue>.GetStringValue(value) ?? string.Empty;
return await _mapperCollection.Value.GetImportValueAsync(importString, propertyType, options);
var result = await _mapperCollection.Value.GetImportValueAsync(importString, propertyType, options);

// When the original value was a non-string JSON type (array, object, number, etc.),
// convert string results back to JsonNode to preserve the correct JSON type
// and prevent double-encoding when the block value is re-serialized.
if (result is string stringResult && value.IsNonStringJsonValue())
{
return stringResult.ConvertToJsonNode() ?? result;
}

return result;
}

private async Task<object?> GetExportProperty(object? value, IPropertyType? propertyType, SyncSerializerOptions options)
Expand Down
Loading