Skip to content

Commit 44aa5dc

Browse files
authored
Provides an abstraction for creating the JavaScriptEncoder used in SystemTextConfigurationEditorJsonSerializer (#19849)
* Provides an abstraction for creating the JavaScriptEncoder used in SystemTextConfigurationEditorJsonSerializer. * Generalised JSON serialization encoder factory to work for all System.Tex.Json serializers. Added the serializer's name as a parameter to allow for different encodings per serializer if required. * Fixed tests by removing use of obsolete constructors. * Removed name parameter and used a generic type instead.
1 parent 3a4e0b0 commit 44aa5dc

File tree

50 files changed

+194
-87
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+194
-87
lines changed

src/Umbraco.Core/Serialization/IJsonSerializer.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ public interface IJsonSerializer
1616
/// </returns>
1717
string Serialize(object? input);
1818

19-
2019
/// <summary>
2120
/// Parses the text representing a single JSON value into an instance of the type specified by a generic type parameter.
2221
/// </summary>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Text.Encodings.Web;
2+
3+
namespace Umbraco.Cms.Core.Serialization;
4+
5+
/// <summary>
6+
/// Provides a factory method for creating a <see cref="JavaScriptEncoder"/> for use in instantiating JSON serializers.
7+
/// </summary>
8+
public interface IJsonSerializerEncoderFactory
9+
{
10+
/// <summary>
11+
/// Creates a <see cref="JavaScriptEncoder"/> for use in the serialization of configuration editor JSON.
12+
/// </summary>
13+
/// <typeparam name="TSerializer">The type of the serializer for which the encoder is being created.</typeparam>
14+
/// <returns>A <see cref="JavaScriptEncoder"/> instance.</returns>
15+
JavaScriptEncoder CreateEncoder<TSerializer>()
16+
where TSerializer : IJsonSerializer;
17+
}

src/Umbraco.Infrastructure/DependencyInjection/UmbracoBuilder.CoreServices.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public static IUmbracoBuilder AddCoreInitialServices(this IUmbracoBuilder builde
127127

128128
builder.Services.AddSingleton<IJsonSerializer, SystemTextJsonSerializer>();
129129
builder.Services.AddSingleton<IConfigurationEditorJsonSerializer, SystemTextConfigurationEditorJsonSerializer>();
130+
builder.Services.AddUnique<IJsonSerializerEncoderFactory, DefaultJsonSerializerEncoderFactory>();
130131
builder.Services.AddUnique<IWebhookJsonSerializer, SystemTextWebhookJsonSerializer>();
131132

132133
// register database builder
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.Text.Encodings.Web;
2+
using System.Text.Unicode;
3+
using Umbraco.Cms.Core.Serialization;
4+
5+
namespace Umbraco.Cms.Infrastructure.Serialization;
6+
7+
/// <inheritdoc />
8+
public sealed class DefaultJsonSerializerEncoderFactory : IJsonSerializerEncoderFactory
9+
{
10+
/// <inheritdoc />
11+
public JavaScriptEncoder CreateEncoder<TSerializer>()
12+
where TSerializer : IJsonSerializer
13+
=> JavaScriptEncoder.Create(UnicodeRanges.BasicLatin);
14+
}

src/Umbraco.Infrastructure/Serialization/SystemTextConfigurationEditorJsonSerializer.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System.Text.Json;
22
using System.Text.Json.Serialization;
33
using System.Text.Json.Serialization.Metadata;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using Umbraco.Cms.Core.DependencyInjection;
46
using Umbraco.Cms.Core.PropertyEditors;
57
using Umbraco.Cms.Core.Serialization;
68

@@ -14,11 +16,24 @@ public sealed class SystemTextConfigurationEditorJsonSerializer : SystemTextJson
1416
/// <summary>
1517
/// Initializes a new instance of the <see cref="SystemTextConfigurationEditorJsonSerializer" /> class.
1618
/// </summary>
19+
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")]
1720
public SystemTextConfigurationEditorJsonSerializer()
21+
: this(
22+
StaticServiceProvider.Instance.GetRequiredService<IJsonSerializerEncoderFactory>())
23+
{
24+
}
25+
26+
/// <summary>
27+
/// Initializes a new instance of the <see cref="SystemTextConfigurationEditorJsonSerializer" /> class.
28+
/// </summary>
29+
public SystemTextConfigurationEditorJsonSerializer(IJsonSerializerEncoderFactory jsonSerializerEncoderFactory)
30+
: base(jsonSerializerEncoderFactory)
1831
=> _jsonSerializerOptions = new JsonSerializerOptions()
1932
{
2033
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
2134

35+
Encoder = jsonSerializerEncoderFactory.CreateEncoder<SystemTextConfigurationEditorJsonSerializer>(),
36+
2237
// In some cases, configs aren't camel cased in the DB, so we have to resort to case insensitive
2338
// property name resolving when creating configuration objects (deserializing DB configs).
2439
PropertyNameCaseInsensitive = true,
@@ -40,6 +55,7 @@ public SystemTextConfigurationEditorJsonSerializer()
4055
.WithAddedModifier(UseAttributeConfiguredPropertyNames()),
4156
};
4257

58+
/// <inheritdoc/>
4359
protected override JsonSerializerOptions JsonSerializerOptions => _jsonSerializerOptions;
4460

4561
/// <summary>

src/Umbraco.Infrastructure/Serialization/SystemTextJsonSerializer.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System.Text.Json;
22
using System.Text.Json.Serialization;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Umbraco.Cms.Core.DependencyInjection;
5+
using Umbraco.Cms.Core.Serialization;
36

47
namespace Umbraco.Cms.Infrastructure.Serialization;
58

@@ -9,12 +12,26 @@ public sealed class SystemTextJsonSerializer : SystemTextJsonSerializerBase
912
private readonly JsonSerializerOptions _jsonSerializerOptions;
1013

1114
/// <summary>
12-
/// Initializes a new instance of the <see cref="SystemTextJsonSerializer" /> class.
15+
/// Initializes a new instance of the <see cref="SystemTextConfigurationEditorJsonSerializer" /> class.
1316
/// </summary>
17+
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")]
1418
public SystemTextJsonSerializer()
19+
: this(
20+
StaticServiceProvider.Instance.GetRequiredService<IJsonSerializerEncoderFactory>())
21+
{
22+
}
23+
24+
/// <summary>
25+
/// Initializes a new instance of the <see cref="SystemTextJsonSerializer" /> class.
26+
/// </summary>
27+
public SystemTextJsonSerializer(IJsonSerializerEncoderFactory jsonSerializerEncoderFactory)
28+
: base(jsonSerializerEncoderFactory)
1529
=> _jsonSerializerOptions = new JsonSerializerOptions
1630
{
1731
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
32+
33+
Encoder = jsonSerializerEncoderFactory.CreateEncoder<SystemTextJsonSerializer>(),
34+
1835
Converters =
1936
{
2037
new JsonStringEnumConverter(),
@@ -25,5 +42,6 @@ public SystemTextJsonSerializer()
2542
}
2643
};
2744

45+
/// <inheritdoc/>
2846
protected override JsonSerializerOptions JsonSerializerOptions => _jsonSerializerOptions;
2947
}

src/Umbraco.Infrastructure/Serialization/SystemTextJsonSerializerBase.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,38 @@
1-
using System.Diagnostics.CodeAnalysis;
1+
using System.Diagnostics.CodeAnalysis;
2+
using System.Text.Encodings.Web;
23
using System.Text.Json;
34
using System.Text.Json.Nodes;
5+
using Microsoft.Extensions.DependencyInjection;
6+
using Umbraco.Cms.Core.DependencyInjection;
47
using Umbraco.Cms.Core.Serialization;
58
using Umbraco.Extensions;
69

710
namespace Umbraco.Cms.Infrastructure.Serialization;
811

912
public abstract class SystemTextJsonSerializerBase : IJsonSerializer
1013
{
14+
private readonly IJsonSerializerEncoderFactory _jsonSerializerEncoderFactory;
15+
16+
/// <summary>
17+
/// Initializes a new instance of the <see cref="SystemTextJsonSerializerBase" /> class.
18+
/// </summary>
19+
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")]
20+
protected SystemTextJsonSerializerBase()
21+
: this(
22+
StaticServiceProvider.Instance.GetRequiredService<IJsonSerializerEncoderFactory>())
23+
{
24+
}
25+
26+
/// <summary>
27+
/// Initializes a new instance of the <see cref="SystemTextJsonSerializerBase"/> class.
28+
/// </summary>
29+
/// <param name="jsonSerializerEncoderFactory">The <see cref="IJsonSerializerEncoderFactory"/> for creating the <see cref="JavaScriptEncoder"/>.</param>
30+
protected SystemTextJsonSerializerBase(IJsonSerializerEncoderFactory jsonSerializerEncoderFactory)
31+
=> _jsonSerializerEncoderFactory = jsonSerializerEncoderFactory;
32+
33+
/// <summary>
34+
/// Gets the <see cref="System.Text.Json.JsonSerializerOptions"/>.
35+
/// </summary>
1136
protected abstract JsonSerializerOptions JsonSerializerOptions { get; }
1237

1338
/// <inheritdoc />
Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
using System.Text.Json;
1+
using System.Text.Json;
22
using System.Text.Json.Serialization;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Umbraco.Cms.Core.DependencyInjection;
35
using Umbraco.Cms.Core.Serialization;
46

57
namespace Umbraco.Cms.Infrastructure.Serialization;
@@ -10,22 +12,37 @@ public sealed class SystemTextWebhookJsonSerializer : SystemTextJsonSerializerBa
1012
private readonly JsonSerializerOptions _jsonSerializerOptions;
1113

1214
/// <summary>
13-
/// Initializes a new instance of the <see cref="SystemTextWebhookJsonSerializer" /> class.
15+
/// Initializes a new instance of the <see cref="SystemTextConfigurationEditorJsonSerializer" /> class.
1416
/// </summary>
17+
[Obsolete("Please use the constructor taking all parameters. Scheduled for removal in Umbraco 18.")]
1518
public SystemTextWebhookJsonSerializer()
19+
: this(
20+
StaticServiceProvider.Instance.GetRequiredService<IJsonSerializerEncoderFactory>())
21+
{
22+
}
23+
24+
/// <summary>
25+
/// Initializes a new instance of the <see cref="SystemTextWebhookJsonSerializer" /> class.
26+
/// </summary>
27+
public SystemTextWebhookJsonSerializer(IJsonSerializerEncoderFactory jsonSerializerEncoderFactory)
28+
: base(jsonSerializerEncoderFactory)
1629
=> _jsonSerializerOptions = new JsonSerializerOptions()
1730
{
1831
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
32+
33+
Encoder = jsonSerializerEncoderFactory.CreateEncoder<SystemTextWebhookJsonSerializer>(),
34+
1935
Converters =
2036
{
2137
new JsonStringEnumConverter(),
2238
new JsonUdiConverter(),
2339
new JsonUdiRangeConverter(),
2440
new JsonObjectConverter(), // Required for block editor values
25-
new JsonBlockValueConverter()
41+
new JsonBlockValueConverter(),
2642
},
2743
TypeInfoResolver = new WebhookJsonTypeResolver(),
2844
};
2945

46+
/// <inheritdoc/>
3047
protected override JsonSerializerOptions JsonSerializerOptions => _jsonSerializerOptions;
3148
}

tests/Umbraco.TestData/UmbracoTestDataController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ private IDataType GetOrCreateDataType(string name, string editorAlias)
299299
throw new InvalidOperationException($"No {editorAlias} editor found");
300300
}
301301

302-
var serializer = new SystemTextConfigurationEditorJsonSerializer();
302+
var serializer = new SystemTextConfigurationEditorJsonSerializer(new DefaultJsonSerializerEncoderFactory());
303303

304304
dt = new DataType(editor, serializer)
305305
{

tests/Umbraco.Tests.Common/Builders/DataTypeBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ public override DataType Build()
138138
var creatorId = _creatorId ?? 1;
139139
var databaseType = _databaseType ?? ValueStorageType.Ntext;
140140
var sortOrder = _sortOrder ?? 0;
141-
var serializer = new SystemTextConfigurationEditorJsonSerializer();
141+
var serializer = new SystemTextConfigurationEditorJsonSerializer(new DefaultJsonSerializerEncoderFactory());
142142

143143
var dataType = new DataType(editor, serializer, parentId)
144144
{

0 commit comments

Comments
 (0)