Newtonsoft accepts what System.Text.Json rejects
If a .NET migration suddenly started failing on files that "always worked", this is why. Newtonsoft.Json is lenient by default; System.Text.Json is strict by default. Measured on both, same inputs.
10 of 11 malformed inputs behave differently
| Malformed input | Newtonsoft 13.0.3 | System.Text.Json (.NET 8) | STJ message |
|---|---|---|---|
| Trailing comma object | accepted | rejected | The JSON object contains a trailing comma at the end whi |
| Trailing comma array | accepted | rejected | The JSON array contains a trailing comma at the end whic |
| Single quotes | accepted | rejected | ''' is an invalid start of a property name. Expected a ' |
| Unquoted key | accepted | rejected | 'a' is an invalid start of a property name. Expected a ' |
| Line comment | accepted | rejected | '/' is invalid after a value. Expected either ',', '}', |
| Block comment | accepted | rejected | '/' is invalid after a value. Expected either ',', '}', |
| Nan literal | accepted | rejected | 'N' is an invalid start of a value. LineNumber: 0 | Byte |
| Infinity literal | accepted | rejected | 'I' is an invalid start of a value. LineNumber: 0 | Byte |
| Leading zero | accepted | rejected | Invalid leading zero before '1'. LineNumber: 0 | BytePos |
| Hex number | accepted | rejected | 'x' is an invalid end of a number. Expected a delimiter. |
| Extra data | rejected | rejected | '{' is invalid after a single JSON value. Expected end o |
"Accepted" means the parser returned a value with no error.
Files that worked for years start failing
Newtonsoft silently tolerates trailing commas, comments, and NaN. Teams have been relying on that without knowing it — a config file with a stray comma has simply worked since it was written.
Switch to System.Text.Json and those files throw. Nothing changed in the data; the tolerance went away.
System.Text.Json can be relaxed with JsonSerializerOptions: AllowTrailingCommas = true and ReadCommentHandling = JsonCommentHandling.Skip. That gets you most of the way, but not to NaN, which STJ will not read under any option.
A practical check
Run your existing JSON corpus through System.Text.Json with default options and log the failures. The list you get back is the set of files that were quietly malformed the whole time.
That is the useful framing: STJ is not breaking your files, it is revealing that they were never valid JSON.
Standards referenced
Every input in the table below is invalid per RFC 8259. Newtonsoft accepting them is an extension, which §9 of RFC 8259 explicitly permits a parser to offer.
- RFC 8259 (STD 90) §2 — JSON Grammar — The JavaScript Object Notation (JSON) Data Interchange Format, T. Bray, Ed., 2017.
- RFC 8259 (STD 90) §4 — Objects — The JavaScript Object Notation (JSON) Data Interchange Format, T. Bray, Ed., 2017.
- RFC 8259 (STD 90) §6 — Numbers — The JavaScript Object Notation (JSON) Data Interchange Format, T. Bray, Ed., 2017.
- ECMA-404, 2nd edition §text — 4 JSON Text — The JSON Data Interchange Syntax, Ecma International, 2017.
Only standards bodies and peer-reviewed venues are cited here.
How this was measured
Both libraries were executed on the same corpus of malformed documents. Newtonsoft.Json 13.0.3 and System.Text.Json on .NET 8.0.30, with default options in both cases.
Every figure on this page came from executing the parser named, not from documentation. The collection harness is public — see the error registry method notes.