Escape JSON in C# and .NET — Newtonsoft vs System.Text.Json
- System.Text.Json (modern .NET) HTML-escapes < > & by default — surprising for non-HTML contexts.
- Newtonsoft.Json escapes less aggressively by default — usually the more intuitive output.
- Both handle required JSON escapes correctly. The difference is in optional escape behavior.
Table of Contents
.NET has two JSON libraries in common use: Newtonsoft.Json (the long-time standard) and System.Text.Json (built-in since .NET Core 3.0). They both handle JSON escape rules correctly, but their default behavior on optional escapes differs — enough that serialized output from one does not byte-match the other. Knowing the differences saves debugging time.
System.Text.Json — HTML-Safe by Default
The modern built-in serializer escapes more aggressively than Newtonsoft. Out of the box, it escapes <, >, &, ', and + as \u escapes:
using System.Text.Json;
JsonSerializer.Serialize(new { msg = "<b>hi&bye</b>" });
// {"msg":"\u003Cb\u003Ehi\u0026bye\u003C/b\u003E"}
This is HTML-safe — the output can be embedded inside a script tag without breaking. It's also surprising if you're not expecting it, and makes logs less readable.
To turn it off, pass JsonSerializerOptions with UnsafeRelaxedJsonEscaping:
var options = new JsonSerializerOptions {
Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
JsonSerializer.Serialize(new { msg = "<b>hi&bye</b>" }, options);
// {"msg":"<b>hi&bye</b>"}
The Unsafe in the name is about HTML-embedding safety, not about JSON validity. The relaxed output is still perfectly valid JSON.
Newtonsoft.Json — Relaxed by Default
Newtonsoft (Json.NET) escapes only what JSON requires — quote, backslash, control characters — and leaves the rest raw:
using Newtonsoft.Json;
JsonConvert.SerializeObject(new { msg = "<b>hi&bye</b>" });
// {"msg":"<b>hi&bye</b>"}
Most people find this more intuitive — the output looks like the input. If you need HTML-safe escaping with Newtonsoft, set StringEscapeHandling.EscapeHtml on the settings.
Newtonsoft also has a StringEscapeHandling.EscapeNonAscii option that escapes all non-ASCII as \u sequences. Useful when target systems don't handle UTF-8 cleanly.
Escaping Individual Strings
For cases where you have a string that needs to become a JSON string literal (not a full object serialization), use one of these patterns:
// System.Text.Json string input = "She said \"hi\""; string escaped = JsonSerializer.Serialize(input); // "She said \"hi\"" // Newtonsoft — same idea string escaped2 = JsonConvert.ToString(input);
Both return the JSON string representation including the surrounding quotes. If you need the escaped content without quotes, trim them:
string inner = escaped.Substring(1, escaped.Length - 2);
This is the standard way to build JSON string values piece by piece. Do not concatenate strings with backslash-escape replaces — the serializer knows the rules better than ad-hoc string manipulation.
Reading Escaped JSON Back Into Objects
Both libraries handle unescape on deserialize:
// System.Text.Json var obj = JsonSerializer.Deserialize<MyType>(jsonString); // Newtonsoft var obj2 = JsonConvert.DeserializeObject<MyType>(jsonString);
Escaped characters come back as their original values. The two libraries can read each other's output — a JSON string serialized by System.Text.Json deserializes correctly in Newtonsoft, and vice versa. Byte-for-byte output may differ, but semantic content is the same.
If you're getting parse errors, the usual cause is that the "JSON" was built by string concatenation and has unescaped quotes or malformed escapes. Validate the string in a JSON formatter first.
Which Library to Pick in 2026
For new .NET projects: System.Text.Json. It's built-in, fast, zero-allocation for hot paths, and well-supported. Override the encoder if you want relaxed escaping.
For older projects already on Newtonsoft: stay with it unless there's a specific reason to migrate. Newtonsoft still has features System.Text.Json doesn't (custom contract resolvers, more flexible converters, LINQ to JSON). Mid-migration is worse than either.
For serializing arbitrary data with complex custom types, Newtonsoft is still often more forgiving. For tight hot paths with known schemas, System.Text.Json wins on performance.
On the escape question specifically — neither is "wrong." System.Text.Json's HTML-safe default prevents a category of security bugs in web rendering contexts. Newtonsoft's relaxed default produces smaller, more readable output. Pick per context.
Escape JSON Outside .NET
For log debugging and cross-stack JSON work. Browser-based, no dependencies.
Open Free JSON Escape / Unescape ToolFrequently Asked Questions
Why does System.Text.Json escape my < and >?
HTML-safe encoding is the default. Pass JavaScriptEncoder.UnsafeRelaxedJsonEscaping to opt out.
Is Newtonsoft still safe to use?
Yes. It is actively maintained, widely deployed, and has no known issues. System.Text.Json is recommended for new code mainly for performance.
How do I escape a string for JSON in C# without serializing an object?
JsonSerializer.Serialize(str) or JsonConvert.ToString(str). Both return a JSON-escaped string value with quotes.
Can I mix System.Text.Json and Newtonsoft in the same project?
Yes, they coexist fine. They read each other's output. Choose per component.

