System.Text.Json vs Newtonsoft.Json in 2026 (Still Relevant?)

Tapesh Mehta Tapesh Mehta | Published on: Feb 19, 2026 | Est. reading time: 8 minutes
System.Text.Json vs Newtonsoft.Json in 2026 (still relevant)

The debate around System.Text.Json vs Newtonsoft.Json has been simmering since Microsoft introduced its built-in JSON library in .NET Core 3.0. Fast-forward to 2026, and developers are still asking: is Newtonsoft.Json even worth considering, or has System.Text.Json completely taken over? In this post, we’ll cut through the noise with real benchmarks, practical code, and clear guidance on when to use each library in modern .NET applications.

Table of Contents

A Quick History: How We Got Here

Newtonsoft.Json (Json.NET) was the de facto standard for JSON serialization in the .NET ecosystem for well over a decade. James Newton-King’s library offered incredible flexibility — custom converters, contract resolvers, dynamic serialization, and more. It became so popular that it was among the most downloaded NuGet packages of all time.

Then, with .NET Core 3.0 in 2019, Microsoft shipped System.Text.Json as a high-performance, allocation-friendly alternative built right into the runtime. The motivation was clear: reduce allocations on the hot path, improve throughput for ASP.NET Core APIs, and eliminate a heavyweight third-party dependency from the default stack. By 2026, with .NET 9 and .NET 10 in the picture, the gap has narrowed dramatically — but it hasn’t fully closed.

If you’re working on performance-critical services or looking at Native AOT compilation in .NET 9, the choice of JSON library can directly impact binary size and startup time — making this comparison more relevant than ever.

Performance: System.Text.Json vs Newtonsoft.Json

Performance is where System.Text.Json vs Newtonsoft.Json shows the sharpest contrast. System.Text.Json was designed from the ground up to minimize heap allocations by working with Span<T> and ReadOnlySpan<byte> internally. Newtonsoft.Json, being older, does not benefit from these modern runtime primitives.

Typical benchmarks (BenchmarkDotNet, .NET 9) show System.Text.Json is roughly 2–3x faster for serialization and uses 40–60% less memory on average for simple POCO objects. For high-throughput APIs handling thousands of requests per second, this is a meaningful difference. Check the official Microsoft docs for the most up-to-date benchmark data: System.Text.Json overview on MSDN.

Serialization Benchmark Example


// Model
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public DateTime CreatedAt { get; set; }
}

// System.Text.Json serialization
using System.Text.Json;

var product = new Product { Id = 1, Name = "Widget", Price = 9.99m, CreatedAt = DateTime.UtcNow };
string json = JsonSerializer.Serialize(product);
Product? deserialized = JsonSerializer.Deserialize<Product>(json);

// Newtonsoft.Json serialization
using Newtonsoft.Json;

string jsonNewton = JsonConvert.SerializeObject(product);
Product? deserializedNewton = JsonConvert.DeserializeObject<Product>(jsonNewton);

Feature Comparison: Where Newtonsoft.Json Still Has the Edge

System.Text.Json has improved significantly over the years, but Newtonsoft.Json still wins in certain areas, particularly when dealing with complex legacy scenarios.

1. Handling of Reference Loops

Newtonsoft.Json has long supported circular reference handling via ReferenceLoopHandling.Ignore or ReferenceLoopHandling.Serialize. System.Text.Json added reference handling support via JsonSerializerOptions.ReferenceHandler, but the API surface is different and migration isn’t always trivial.


// System.Text.Json - handle circular references
var options = new JsonSerializerOptions
{
    ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.Preserve,
    WriteIndented = true
};
string json = JsonSerializer.Serialize(myObjectWithCycles, options);

// Newtonsoft.Json - handle reference loops
var settings = new JsonSerializerSettings
{
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    Formatting = Formatting.Indented
};
string jsonNewton = JsonConvert.SerializeObject(myObjectWithCycles, settings);

2. Dynamic and Anonymous Types

Newtonsoft.Json handles dynamic and JObject/JArray with natural ease. System.Text.Json uses JsonElement and JsonDocument for DOM-style access, which is more verbose but more allocation-friendly. If your codebase heavily uses dynamic deserialization or ExpandoObject, migrating to System.Text.Json can require significant refactoring.

3. Custom Converters and Contract Resolvers

Newtonsoft’s IContractResolver and JsonConverter ecosystem is vast and mature. System.Text.Json introduced JsonConverter<T> and, from .NET 7 onwards, IJsonTypeInfoResolver for advanced customization. However, if you’re relying on community converters built for Newtonsoft.Json, you’ll need to find or write equivalents. This is one of the main blockers for enterprise migrations from large codebases.

System.Text.Json Advanced Features in .NET 8 and .NET 9

Microsoft has been closing the gap rapidly. Here are notable improvements that make System.Text.Json even more compelling in 2026:

Source Generation for Zero-Overhead Serialization

Source generation eliminates reflection at runtime, making System.Text.Json a perfect fit for Native AOT and trimmed deployments. This is something Newtonsoft.Json fundamentally cannot offer due to its reliance on reflection.


using System.Text.Json;
using System.Text.Json.Serialization;

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Product))]
[JsonSerializable(typeof(List<Product>))]
public partial class ProductJsonContext : JsonSerializerContext { }

// Usage - no reflection at runtime
string json = JsonSerializer.Serialize(product, ProductJsonContext.Default.Product);
Product? result = JsonSerializer.Deserialize(json, ProductJsonContext.Default.Product);

This approach is particularly powerful when combined with our guide on improving ASP.NET Core web application performance, as it removes serialization overhead from the hot path entirely.

Required Properties and Polymorphism (.NET 7+)

System.Text.Json now supports required properties via the [JsonRequired] attribute and polymorphic serialization via [JsonDerivedType], features that were previously only available in Newtonsoft.Json through workarounds.


using System.Text.Json.Serialization;

[JsonDerivedType(typeof(Dog), typeDiscriminator: "dog")]
[JsonDerivedType(typeof(Cat), typeDiscriminator: "cat")]
public abstract class Animal
{
    public string Name { get; set; } = string.Empty;
}

public class Dog : Animal { public string Breed { get; set; } = string.Empty; }
public class Cat : Animal { public bool IsIndoor { get; set; } }

// Polymorphic round-trip
Animal[] animals = [new Dog { Name = "Rex", Breed = "Labrador" }, new Cat { Name = "Whiskers", IsIndoor = true }];
string json = JsonSerializer.Serialize(animals);
Animal[]? deserialized = JsonSerializer.Deserialize<Animal[]>(json);

Practical Migration: Moving from Newtonsoft.Json to System.Text.Json

Migration is often the toughest part. If you’re working on migrating from ASP.NET Framework to ASP.NET Core, you’ll encounter this decision directly. Here’s a common pattern comparison:


// --- Newtonsoft.Json patterns and their System.Text.Json equivalents ---

// 1. Ignore null values
// Newtonsoft:
var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
// System.Text.Json:
var options = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };

// 2. Camel case property names
// Newtonsoft:
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// System.Text.Json:
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;

// 3. Custom date format
// Newtonsoft:
settings.DateFormatString = "yyyy-MM-dd";
// System.Text.Json: requires a custom JsonConverter<DateTime>

// 4. Enum as string
// Newtonsoft:
settings.Converters.Add(new StringEnumConverter());
// System.Text.Json:
options.Converters.Add(new JsonStringEnumConverter());

Note that date format customization in System.Text.Json still requires a custom converter, which is one of the remaining rough edges. The official Microsoft migration guide covers the full list of behavioral differences — it’s worth reading before starting a migration on a large codebase.

Security Considerations

From a security standpoint, System.Text.Json is more strict by default. It doesn’t support TypeNameHandling, which in Newtonsoft.Json was a known vector for deserialization attacks when set to non-None values. This makes System.Text.Json inherently safer out of the box for applications that handle untrusted JSON input.

If you’re building applications with strict security requirements, this is a compelling reason to prefer System.Text.Json — and it aligns with the broader guidance in our post on best practices for securing .NET applications.

Testing JSON Serialization Behavior

Regardless of which library you choose, it’s important to test serialization contracts in your application — especially when upgrading library versions or switching between the two. As covered in our guide on unit testing in .NET: best practices and tools, writing dedicated serialization tests prevents subtle bugs from reaching production.


using System.Text.Json;
using Xunit;

public class ProductSerializationTests
{
    [Fact]
    public void Serialize_Product_ProducesExpectedJson()
    {
        var product = new Product { Id = 1, Name = "Widget", Price = 9.99m, CreatedAt = new DateTime(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc) };
        var options = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };

        string json = JsonSerializer.Serialize(product, options);

        Assert.Contains("\"id\":1", json);
        Assert.Contains("\"name\":\"Widget\"", json);
        Assert.Contains("\"price\":9.99", json);
    }

    [Fact]
    public void Deserialize_Json_ReturnsCorrectProduct()
    {
        string json = "{\"id\":2,\"name\":\"Gadget\",\"price\":19.99,\"createdAt\":\"2026-01-01T00:00:00Z\"}";
        var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };

        Product? result = JsonSerializer.Deserialize<Product>(json, options);

        Assert.NotNull(result);
        Assert.Equal(2, result.Id);
        Assert.Equal("Gadget", result.Name);
    }
}

When to Still Use Newtonsoft.Json in 2026

Despite System.Text.Json’s rapid advancement, there are legitimate reasons to keep Newtonsoft.Json:

Legacy codebases: If you have a large codebase with deep Newtonsoft.Json integration (custom resolvers, converters, JObject usage everywhere), migrating is a significant engineering effort with real risk. Stability may outweigh the performance gains.

Complex dynamic JSON: Applications that parse highly dynamic or schema-less JSON where you need LINQ-to-JSON (JToken, JArray) still benefit from Newtonsoft’s ergonomics, though System.Text.Json’s JsonNode API (added in .NET 6) has become a solid alternative.

Third-party library compatibility: Some older third-party libraries explicitly depend on Newtonsoft.Json types. In those cases, you often can’t avoid it without forking or replacing the dependency.

Specific serialization edge cases: Features like preserving property order from a source object, extremely flexible polymorphic hierarchies without known discriminators, or deep JToken manipulation may still be easier with Newtonsoft.

Quick Decision Guide

Use System.Text.Json if: you’re building a new project on .NET 6+, performance and allocation matter, you’re targeting Native AOT, or you want fewer dependencies and built-in ASP.NET Core integration.

Stick with Newtonsoft.Json if: you have a large existing codebase that would require extensive migration, you rely on advanced dynamic JSON features, or a third-party dependency forces the choice.

For greenfield .NET applications developed by a professional .NET development team, System.Text.Json is the default recommendation today. It’s faster, more memory-efficient, natively integrated, and actively invested in by Microsoft.

Conclusion

The System.Text.Json vs Newtonsoft.Json debate in 2026 has a clear lean: System.Text.Json wins for new development. Microsoft has addressed most of the gaps — polymorphism, required properties, reference handling, source generation — making it a production-ready choice for the vast majority of use cases. Newtonsoft.Json remains relevant for legacy migrations and niche scenarios, but its days as the default choice are behind it.

The key takeaway is that this isn’t an all-or-nothing decision. Both libraries can coexist in the same solution if needed, and the migration path is well-documented. Evaluate your specific requirements, test your serialization contracts thoroughly, and make the switch to System.Text.Json when the time is right for your project.

Share

clutch profile designrush wirefuture profile goodfirms wirefuture profile
Precision-Crafted Software for Every Need! 🔍

WireFuture stands for precision in every line of code. Whether you're a startup or an established enterprise, our bespoke software solutions are tailored to fit your exact requirements.

Hire Now

Categories
.NET Development Angular Development JavaScript Development KnockoutJS Development NodeJS Development PHP Development Python Development React Development Software Development SQL Server Development VueJS Development All
About Author
wirefuture - founder

Tapesh Mehta

verified Verified
Expert in Software Development

Tapesh Mehta is a seasoned tech worker who has been making apps for the web, mobile devices, and desktop for over 15+ years. Tapesh knows a lot of different computer languages and frameworks. For robust web solutions, he is an expert in Asp.Net, PHP, and Python. He is also very good at making hybrid mobile apps, which use Ionic, Xamarin, and Flutter to make cross-platform user experiences that work well together. In addition, Tapesh has a lot of experience making complex desktop apps with WPF, which shows how flexible and creative he is when it comes to making software. His work is marked by a constant desire to learn and change.

Get in Touch
Your Ideas, Our Strategy – Let's Connect.

No commitment required. Whether you’re a charity, business, start-up or you just have an idea – we’re happy to talk through your project.

Embrace a worry-free experience as we proactively update, secure, and optimize your software, enabling you to focus on what matters most – driving innovation and achieving your business goals.

Hire Your A-Team Here to Unlock Potential & Drive Results
You can send an email to contact@wirefuture.com
clutch wirefuture profile designrush wirefuture profile goodfirms wirefuture profile good firms award-4 award-5 award-6