'Un-escape specific characters when serializing to JSON in C#
I have a simple task which is to unescape an apostrophe when serializing to JSON using System.Text.JSON:
using System;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Unicode;
namespace DebugApp;
internal class Program
{
private static void Main(string[] args)
{
var input = new Item
{
Text = "'"
};
var encoderSettings = new TextEncoderSettings();
encoderSettings.AllowCharacters('\u0027', '\'');
encoderSettings.AllowRange(UnicodeRanges.BasicLatin);
var options = new JsonSerializerOptions
{
Encoder = JavaScriptEncoder.Create(encoderSettings)
};
var json = JsonSerializer.Serialize(input, options);
Console.WriteLine("Serialized json: {0}", json);
}
private class Item
{
public string Text { get; set; }
}
}
I expect the outcome to be Serialized json: {"Text":"'"}
Unfortunately, I am still getting Serialized json: {"Text":"\u0027"}
I referred to the Microsoft documentation here => Serialize specific characters
What am I doing wrong?
Solution 1:[1]
Use Newtonsoft.Json and you always will be happy. But if you still want to use System.Text.Json , use this System.Text.RegularExpressions function
json = System.Text.RegularExpressions.Regex.Unescape(
System.Text.Json.JsonSerializer.Serialize(input));
or more simple
json = System.Text.Json.JsonSerializer.Serialize(input).Replace("\\u0027","'");
result
{"Text":"'"}
Solution 2:[2]
Unfortunately this is not supported in the current version of .NET.
You could do this with your own encoder, but that would require rewriting huge chunks of code.
Instead, you can do this with some rather nasty reflection. Please note that this code is quite brittle and likely to break on a different version of .NET. It doesn't work on .NET 4, as the internal code is different.
private static void Main(string[] args)
{
var input = new Item
{
Text = "'"
};
var encoderSettings = new TextEncoderSettings();
encoderSettings.AllowRange(UnicodeRanges.BasicLatin);
var encoder = System.Text.Encodings.Web.JavaScriptEncoder.Create(encoderSettings);
var innerEncoder = encoder.GetType().GetField("_innerEncoder", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(encoder);
var codePoints = innerEncoder.GetType().GetField("_allowedBmpCodePoints", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(innerEncoder);
codePoints.GetType().GetMethod("AllowChar").Invoke(codePoints, new object[]{ '\''});
// codePoints is a struct so need to write it back
innerEncoder.GetType().GetField("_allowedBmpCodePoints", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(innerEncoder, codePoints);
var options = new JsonSerializerOptions
{
Encoder = encoder,
};
var json = JsonSerializer.Serialize(input, options);
Console.WriteLine("Serialized json: {0}", json);
}
private class Item
{
public string Text { get; set; }
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | Charlieface |
