diff --git a/Fluid.Tests/MiscFiltersTests.cs b/Fluid.Tests/MiscFiltersTests.cs
index 616ef56a..97d3aaed 100644
--- a/Fluid.Tests/MiscFiltersTests.cs
+++ b/Fluid.Tests/MiscFiltersTests.cs
@@ -1,10 +1,11 @@
-using System;
-using System.Globalization;
-using System.Linq;
-using System.Threading.Tasks;
using Fluid.Filters;
using Fluid.Values;
using Newtonsoft.Json.Linq;
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Text.Encodings.Web;
+using System.Threading.Tasks;
using TimeZoneConverter;
using Xunit;
@@ -779,6 +780,29 @@ public async Task JsonShouldWriteValuesWithCorrectDataTypeForJObjectInput()
Assert.Equal(expected, result.ToStringValue());
}
+ [Fact]
+ public async Task JsonShouldEncodeUnicodeChars()
+ {
+ var input = FluidValue.Create("你好,这是一条短信", TemplateOptions.Default);
+ var result = await MiscFilters.Json(input, new FilterArguments(), new TemplateContext(TemplateOptions.Default));
+ var expected = @"""\u4F60\u597D\uFF0C\u8FD9\u662F\u4E00\u6761\u77ED\u4FE1""";
+ Assert.Equal(expected, result.ToStringValue());
+ }
+
+ [Fact]
+ public async Task JsonShouldUseJsonSerializerOption()
+ {
+ var options = new TemplateOptions
+ {
+ JavaScriptEncoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+ };
+
+ var input = FluidValue.Create("你好,这是一条短信", options);
+ var result = await MiscFilters.Json(input, new FilterArguments(), new TemplateContext(options));
+ var expected = @"""你好,这是一条短信""";
+ Assert.Equal(expected, result.ToStringValue());
+ }
+
[Theory]
[InlineData("", "", "", "0")]
[InlineData(123456, "", "", "123456")]
diff --git a/Fluid/Filters/MiscFilters.cs b/Fluid/Filters/MiscFilters.cs
index b2bfd79b..4c248feb 100644
--- a/Fluid/Filters/MiscFilters.cs
+++ b/Fluid/Filters/MiscFilters.cs
@@ -774,7 +774,7 @@ private static async ValueTask WriteJson(Utf8JsonWriter writer, FluidValue input
}
break;
case FluidValues.String:
- writer.WriteStringValue(input.ToStringValue());
+ writer.WriteStringValue(JsonEncodedText.Encode(input.ToStringValue(), ctx.Options.JavaScriptEncoder));
break;
case FluidValues.Blank:
writer.WriteStringValue(string.Empty);
diff --git a/Fluid/TemplateOptions.cs b/Fluid/TemplateOptions.cs
index cda8a0a5..92484740 100644
--- a/Fluid/TemplateOptions.cs
+++ b/Fluid/TemplateOptions.cs
@@ -2,6 +2,8 @@
using Fluid.Values;
using Microsoft.Extensions.FileProviders;
using System.Globalization;
+using System.Text.Encodings.Web;
+using System.Text.Json;
namespace Fluid
{
@@ -21,6 +23,8 @@ public class TemplateOptions
public static readonly TemplateOptions Default = new();
+ private static readonly JavaScriptEncoder DefaultJavaScriptEncoder = JavaScriptEncoder.Default;
+
///
/// Gets ot sets the members than can be accessed in a template.
///
@@ -89,6 +93,11 @@ public class TemplateOptions
///
public AssignedDelegate Assigned { get; set; }
+ ///
+ /// Gets or sets the instance used by the json filter.
+ ///
+ public JavaScriptEncoder JavaScriptEncoder { get; set; } = DefaultJavaScriptEncoder;
+
///
/// Gets or sets the default trimming rules.
///
@@ -99,7 +108,6 @@ public class TemplateOptions
///
public bool Greedy { get; set; } = true;
-
public TemplateOptions()
{
Filters.WithArrayFilters()
diff --git a/README.md b/README.md
index dd7b38e5..4a2a89b1 100644
--- a/README.md
+++ b/README.md
@@ -335,16 +335,35 @@ Not encoded: {{ html | raw }
When using `capture` blocks, the inner content is flagged as
pre-encoded and won't be double-encoded if used in a `{{ }}` tag.
-#### Source
+### JSON encoding
+
+By default all JSON strings are encoded using the default `JavaScriptEncoder` instance. This can be changed by setting the `TemplateOptions.JavaScriptEncoder` property.
+
```Liquid
-{% capture breaktag %}
{% endcapture %}
+{{ "你好,这是一条短信" | json" }}
+```
+
+#### Result
+
+```html
+"\u4F60\u597D\uFF0C\u8FD9\u662F\u4E00\u6761\u77ED\u4FE1"
+```
-{{ breaktag }}
+Using the `JavaScriptEncoder.UnsafeRelaxedJsonEscaping` can be done this way:
+
+```csharp
+// This variable should be static and reused for all templates
+var options = new TemplateOptions
+{
+ JavaScriptEncoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
+};
+
+var context = new TemplateContext(options);
```
#### Result
```html
-
+"你好,这是一条短信"
```