Newtonsoft.Json
Library
Newtonsoft.Json
Overview
Newtonsoft.Json (Json.NET) is the standard .NET JSON library with 6 billion downloads. With rich features and customizability, it can handle complex object graphs and has been trusted as the standard in the .NET ecosystem for years. It provides comprehensive enterprise-grade JSON processing capabilities including LINQ to JSON, custom converters, error handling, and date format processing, making it an important choice for applications requiring complex customization.
Details
Newtonsoft.Json 13.0.3 is a mature library that continues to be widely used in existing .NET applications. While migration to System.Text.Json is recommended for new projects, it remains an important choice when complex customization, legacy code compatibility, or advanced schema validation features are required. It provides diverse functionality including simple API through JsonConvert static class, streaming via JsonSerializer, LINQ to JSON with JObject/JArray/JToken, rich custom attributes, and property name conversion rules.
Key Features
- Rich Customization Options: Custom converters, naming conventions, date formats, etc.
- LINQ to JSON: Dynamic JSON manipulation with JObject, JArray, JToken
- Advanced Error Handling: Detailed error information and flexible processing
- Comprehensive Attributes: JsonProperty, JsonIgnore, JsonConverter, etc.
- Diverse Configuration: Fine-grained control with DefaultValueHandling, NullValueHandling, etc.
- Schema Validation: JSON Schema validation functionality
Pros and Cons
Pros
- High stability and reliability from over 10 years of development
- Rich customization features and flexible configuration options
- Dynamic JSON manipulation and query capabilities with LINQ to JSON
- Handling of complex object graphs and cyclic references
- Detailed documentation and abundant community resources
- JSON Schema validation and custom converter support
Cons
- Inferior performance compared to System.Text.Json with higher memory usage
- Performance overhead due to reflection-based implementation
- External dependency rather than standard library in .NET Core/.NET 5+
- Some APIs are complex with high learning costs
- Limited compatibility with AOT (Ahead-of-Time) compilation
- Impact on file size and startup time
Reference Pages
Usage Examples
Basic Setup
<!-- .csproj file -->
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
// Basic serialization
var product = new Product { Name = "Apple", Price = 1.99m };
string json = JsonConvert.SerializeObject(product);
// Basic deserialization
var deserializedProduct = JsonConvert.DeserializeObject<Product>(json);
Advanced Configuration and Customization
// Custom serialization settings
var settings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.IsoDateFormat,
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore,
Formatting = Formatting.Indented,
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
string json = JsonConvert.SerializeObject(data, settings);
// Using custom converter
public class CustomDateTimeConverter : JsonConverter<DateTime>
{
public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString("yyyy-MM-dd HH:mm:ss"));
}
public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
return DateTime.ParseExact((string)reader.Value, "yyyy-MM-dd HH:mm:ss", null);
}
}
LINQ to JSON Operations
// Dynamic JSON manipulation with JObject
var jObject = new JObject
{
["name"] = "Product Name",
["price"] = 29.99,
["categories"] = new JArray("electronics", "gadgets"),
["specifications"] = new JObject
{
["weight"] = "500g",
["dimensions"] = "10x5x2 cm"
}
};
// Convert to JSON string
string json = jObject.ToString();
// Data retrieval from JObject
string name = (string)jObject["name"];
decimal price = (decimal)jObject["price"];
var categories = jObject["categories"].ToObject<string[]>();
// Search with LINQ queries
var expensiveProducts = jObject
.Where(p => (decimal)p["price"] > 20)
.Select(p => p["name"])
.ToList();
Performance Optimization
// Streaming with JsonSerializer
using (var stringWriter = new StringWriter())
using (var jsonWriter = new JsonTextWriter(stringWriter))
{
var serializer = new JsonSerializer();
serializer.Serialize(jsonWriter, largeDataObject);
string json = stringWriter.ToString();
}
// Asynchronous deserialization
public async Task<T> DeserializeAsync<T>(Stream stream)
{
using (var reader = new StreamReader(stream))
using (var jsonReader = new JsonTextReader(reader))
{
var serializer = new JsonSerializer();
return await Task.Run(() => serializer.Deserialize<T>(jsonReader));
}
}
// Performance settings
var settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
FloatParseHandling = FloatParseHandling.Decimal
};
Error Handling and Validation
// Error handling configuration
var settings = new JsonSerializerSettings
{
Error = (sender, args) =>
{
Console.WriteLine($"Error: {args.ErrorContext.Error.Message}");
args.ErrorContext.Handled = true;
},
MissingMemberHandling = MissingMemberHandling.Error
};
try
{
var result = JsonConvert.DeserializeObject<Product>(json, settings);
}
catch (JsonException ex)
{
Console.WriteLine($"JSON parsing error: {ex.Message}");
}
// Conditional serialization
public class Product
{
public string Name { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
public decimal? Price { get; set; }
[JsonIgnore]
public string InternalId { get; set; }
public bool ShouldSerializePrice()
{
return Price.HasValue && Price > 0;
}
}
ASP.NET Core Integration
// Startup.cs or Program.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
options.SerializerSettings.DateFormatHandling = DateFormatHandling.IsoDateFormat;
options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
});
}
// Usage in API controller
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
[HttpPost]
public IActionResult CreateProduct([FromBody] Product product)
{
// Automatic deserialization by Newtonsoft.Json
return Ok(new { Success = true, Product = product });
}
}
// Custom response format
public class ApiResponse<T>
{
[JsonProperty("data")]
public T Data { get; set; }
[JsonProperty("success")]
public bool Success { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("timestamp")]
public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}
Legacy System Integration
// Complex mapping and customization
public class LegacySystemAdapter
{
private readonly JsonSerializerSettings _settings;
public LegacySystemAdapter()
{
_settings = new JsonSerializerSettings
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
},
Converters = { new LegacyDateTimeConverter(), new LegacyBooleanConverter() },
TypeNameHandling = TypeNameHandling.Auto
};
}
public string SerializeForLegacySystem<T>(T data)
{
return JsonConvert.SerializeObject(data, _settings);
}
public T DeserializeFromLegacySystem<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json, _settings);
}
}
// Complex type conversion
public class LegacyDateTimeConverter : JsonConverter<DateTime>
{
public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer)
{
// Special date format for legacy system
writer.WriteValue(value.ToString("yyyyMMddHHmmss"));
}
public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
var dateString = (string)reader.Value;
return DateTime.ParseExact(dateString, "yyyyMMddHHmmss", null);
}
}