ModelingEvolution.JsonParsableConverter 1.0.1

JsonParsableConverter

NuGet License: MIT .NET

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:

  1. Consistency: Same parsing logic for JSON, string manipulation, and user input
  2. Maintainability: Single source of truth for parsing logic
  3. Framework Support: Leverages built-in .NET abstractions
  4. 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.

Showing the top 20 packages that depend on ModelingEvolution.JsonParsableConverter.

Packages Downloads
RocketWelder.SDK.Types
Value types and abstractions for RocketWelder SDK. Contains lightweight identifiers (SessionStreamId, VideoRecordingIdentifier) with no heavy dependencies. Suitable for browser-wasm and other constrained environments.
163
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.
159
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.
153
ModelingEvolution.PerformanceMonitor.Shared
Shared models and DTOs for the ModelingEvolution Performance Monitor system. Includes MessagePack-serializable metric types for CPU, GPU, Network, Disk, Docker containers, and RAM monitoring.
146
ModelingEvolution.EventPi.NetworkMonitor
Package Description
146
ModelingEvolution.FileSystem
Strongly-typed file system path handling with AbsolutePath and RelativePath value types. Features intuitive path arithmetic operators (Relative + Relative, Absolute + Relative, Absolute - Absolute), cross-platform normalization, IParsable support, and JSON serialization.
122
ModelingEvolution.Ide
Package Description
121
RocketWelder.SDK.Types
Value types and abstractions for RocketWelder SDK. Contains lightweight identifiers (SessionStreamId, VideoRecordingIdentifier) with no heavy dependencies. Suitable for browser-wasm and other constrained environments.
78
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.
70
RocketWelder.SDK.Automation
Abstractions for RocketWelder automation programs (IProgram, IProgramContext, etc.)
65
RocketWelder.SDK.Types
Value types and abstractions for RocketWelder SDK. Contains lightweight identifiers (SessionStreamId, VideoRecordingIdentifier) with no heavy dependencies. Suitable for browser-wasm and other constrained environments.
62
RocketWelder.SDK.Automation
Abstractions for RocketWelder automation programs (IProgram, IProgramContext, etc.)
62
ModelingEvolution.FileSystem
Strongly-typed file system path handling with AbsolutePath and RelativePath value types. Features intuitive path arithmetic operators (Relative + Relative, Absolute + Relative, Absolute - Absolute), cross-platform normalization, IParsable support, and JSON serialization.
42
ModelingEvolution.Ide
Package Description
42
ModelingEvolution.Ide.Blazor
Package Description
37
ModelingEvolution.HdrSplitControl
HDR Split Canvas Controls for Blazor
36
RocketWelder.SDK.Types
Value types and abstractions for RocketWelder SDK. Contains lightweight identifiers (SessionStreamId, VideoRecordingIdentifier) with no heavy dependencies. Suitable for browser-wasm and other constrained environments.
25
RocketWelder.SDK.Types
Value types and abstractions for RocketWelder SDK. Contains lightweight identifiers (SessionStreamId, VideoRecordingIdentifier) with no heavy dependencies. Suitable for browser-wasm and other constrained environments.
15
RocketWelder.SDK.Automation
Abstractions for RocketWelder automation programs (IProgram, IProgramContext, etc.)
15
RocketWelder.SDK.Automation
Abstractions for RocketWelder automation programs (IProgram, IProgramContext, etc.)
10

.NET 9.0

  • No dependencies.

Version Downloads Last updated
1.0.1 157 02/10/2026
1.0.0 152 02/10/2026