ModelingEvolution.JsonParsableConverter
1.0.1
dotnet add package ModelingEvolution.JsonParsableConverter --version 1.0.1
NuGet\Install-Package ModelingEvolution.JsonParsableConverter -Version 1.0.1
<PackageReference Include="ModelingEvolution.JsonParsableConverter" Version="1.0.1" />
<PackageVersion Include="ModelingEvolution.JsonParsableConverter" Version="1.0.1" />
<PackageReference Include="ModelingEvolution.JsonParsableConverter" />
paket add ModelingEvolution.JsonParsableConverter --version 1.0.1
#r "nuget: ModelingEvolution.JsonParsableConverter, 1.0.1"
#:package ModelingEvolution.JsonParsableConverter@1.0.1
#addin nuget:?package=ModelingEvolution.JsonParsableConverter&version=1.0.1
#tool nuget:?package=ModelingEvolution.JsonParsableConverter&version=1.0.1
JsonParsableConverter
A high-performance System.Text.Json converter for types implementing IParsable<T>. This library enables seamless JSON serialization/deserialization for custom value types, records, and structs using the standard .NET IParsable pattern.
Features
- 🚀 High Performance: Leverages System.Text.Json for optimal performance
- 🎯 Type Safe: Full compile-time type safety with generic constraints
- 🔧 Easy Integration: Simple registration with JsonSerializerOptions
- 📦 Minimal Dependencies: Only depends on System.Text.Json
- 🧩 DDD Friendly: Perfect for Domain-Driven Design value objects and strongly-typed IDs
Installation
dotnet add package ModelingEvolution.JsonParsableConverter
Quick Start
Define a Parsable Type
using System.Text.Json.Serialization;
using ModelingEvolution.JsonParsableConverter;
[JsonConverter(typeof(JsonParsableConverter<ProductId>))]
public readonly record struct ProductId(Guid Value) : IParsable<ProductId>
{
public static ProductId Parse(string s, IFormatProvider? provider)
=> new(Guid.Parse(s));
public static bool TryParse(string? s, IFormatProvider? provider, out ProductId result)
{
if (Guid.TryParse(s, out var guid))
{
result = new ProductId(guid);
return true;
}
result = default;
return false;
}
public override string ToString() => Value.ToString();
}
Usage
With the attribute applied, the type automatically uses the converter - no additional configuration needed:
var productId = new ProductId(Guid.NewGuid());
// Just works - no special JsonSerializerOptions needed!
string json = JsonSerializer.Serialize(productId);
ProductId deserialized = JsonSerializer.Deserialize<ProductId>(json);
Advanced Usage
More Examples
String-based value type:
[JsonConverter(typeof(JsonParsableConverter<CustomerName>))]
public readonly record struct CustomerName(string Value) : IParsable<CustomerName>
{
public static CustomerName Parse(string s, IFormatProvider? provider)
=> new(s);
public static bool TryParse(string? s, IFormatProvider? provider, out CustomerName result)
{
result = new CustomerName(s ?? string.Empty);
return s != null;
}
public override string ToString() => Value;
}
Complex value type with validation:
[JsonConverter(typeof(JsonParsableConverter<Email>))]
public readonly record struct Email : IParsable<Email>
{
private readonly string _value;
public Email(string value)
{
if (!IsValid(value))
throw new ArgumentException("Invalid email format", nameof(value));
_value = value;
}
public static Email Parse(string s, IFormatProvider? provider)
{
if (!IsValid(s))
throw new FormatException($"Invalid email format: {s}");
return new Email(s);
}
public static bool TryParse(string? s, IFormatProvider? provider, out Email result)
{
if (s != null && IsValid(s))
{
result = new Email(s);
return true;
}
result = default;
return false;
}
private static bool IsValid(string email)
=> !string.IsNullOrWhiteSpace(email) && email.Contains('@');
public override string ToString() => _value;
}
Using in Complex Types
Since the converter is applied via attributes, it works seamlessly in complex objects:
public class Order
{
public OrderId Id { get; set; }
public CustomerId CustomerId { get; set; }
public Money TotalAmount { get; set; }
public DateOnly OrderDate { get; set; }
}
public class Customer
{
public CustomerId Id { get; set; }
public CustomerName Name { get; set; }
public Email Email { get; set; }
}
// No special configuration needed - just serialize!
var customer = new Customer
{
Id = CustomerId.Parse("12345", null),
Name = new CustomerName("John Doe"),
Email = Email.Parse("john@example.com", null)
};
string json = JsonSerializer.Serialize(customer);
Customer deserialized = JsonSerializer.Deserialize<Customer>(json);
Why IParsable?
The IParsable<T> interface was introduced in .NET 7 as a standard way to define parsing behavior for custom types. Using this pattern with JSON serialization provides:
- Consistency: Same parsing logic for JSON, string manipulation, and user input
- Maintainability: Single source of truth for parsing logic
- Framework Support: Leverages built-in .NET abstractions
- Type Safety: Compile-time guarantees with generic constraints
Performance
This converter is designed for high performance:
- Zero allocations for value type conversions
- Minimal overhead compared to manual serialization
- Efficient string handling using
Utf8JsonReader/Writer
Requirements
- .NET 9.0 or higher
- System.Text.Json
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
This converter is inspired by the need for better value object support in System.Text.Json and is based on patterns from the MicroPlumberd project.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net9.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on ModelingEvolution.JsonParsableConverter:
| Package | Downloads |
|---|---|
|
RocketWelder.SDK
High-performance video streaming client library for RocketWelder services with zero-copy shared memory support |
|
|
ModelingEvolution.NetworkManager
A .NET wrapper for NetworkManager D-Bus interface providing comprehensive network management capabilities for Linux systems. Supports WiFi, Ethernet, bridging, and advanced network configuration. |
|
|
ModelingEvolution.Ipv4
A lightweight and high-performance IPv4 address library for .NET. Provides strongly-typed IPv4 addresses, network calculations, CIDR notation support, and JSON serialization. Perfect for network programming, configuration management, and Domain-Driven Design applications. |
GitHub repositories
This package is not used by any popular GitHub repositories.