Nerdbank.Json
Package Description
Install
| Product | Versions |
|---|---|
| .NET | |
| .NET Standard | |
| Other |
README
Nerdbank.Json
Nerdbank.Json is a UTF-8 JSON serializer being built in the same general shape as Nerdbank.MessagePack, but without layering on top of System.Text.Json, Newtonsoft.Json, or any other serializer.
The current implementation includes a low-level writer/reader pair, a built-in converter table for common .NET types, and an initial PolyType-backed object serializer for mutable object graphs. It is allocation-conscious in the hot path and multi-targets net8.0, net9.0, net472, and netstandard2.0.
Features
- Direct UTF-8 JSON writing to
IBufferWriter<byte>. - RFC 8259 string escaping, limited to the characters that must be escaped.
- Built-in serialization and deserialization for common .NET primitive and BCL types.
- PolyType-driven serialization for object graphs with settable properties.
- Mutable
ICollection<T>implementations with public parameterless constructors, includingList<T>. - Mutable
IDictionary<string, TValue>implementations with public parameterless constructors, includingDictionary<string, TValue>. - camelCase property naming by default, configurable with
JsonNamingPolicy. - Optional indented output for human-readable JSON.
- Optional case-insensitive property-name matching during deserialization.
- Optional enum-name serialization with numeric fallback for unnamed values.
- Runtime custom converter registration with converter instances, converter types, or converter factories.
- Attribute-driven custom converter registration on types, properties, and constructor parameters.
- Optional unknown-member retention through
JsonExtensionDataAttribute. - Built-in byte buffer handling using Base64 JSON strings.
- Optional trailing-comma and comment skipping support during deserialization.
- Configurable deserialization policy for missing required values and non-nullable reference validation.
- Optional acyclic reference preservation.
- Synchronous stream and async stream overloads.
- Multi-targeting across modern .NET and .NET Framework.
- Test-driven development with focused round-trip coverage for the current built-in type surface.
Supported Built-In Types
The current built-in serializer supports:
string,char,bool- Numeric primitives:
byte,sbyte,short,ushort,int,uint,long,ulong,float,double,decimal System.Numerics.BigIntegerDateTime,DateTimeOffset,TimeSpanGuid,Version,Uri,CultureInfo,Encodingbyte[],Memory<byte>,ReadOnlyMemory<byte>System.Drawing.Color,System.Drawing.Point- On .NET 8 and later:
Half,Int128,UInt128,DateOnly,TimeOnly,Rune
Example
using Nerdbank.Json;
JsonSerializer serializer = new();
string json = serializer.Serialize(new DateTimeOffset(2024, 7, 1, 12, 34, 56, TimeSpan.Zero));
DateTimeOffset value = serializer.Deserialize<DateTimeOffset>(json);
For mutable object graphs, annotate your root type with GenerateShape and use the same serializer APIs:
using Nerdbank.Json;
using PolyType;
[GenerateShape]
public partial class Person
{
public string? Name { get; set; }
public int Age { get; set; }
}
JsonSerializer serializer = new();
string json = serializer.Serialize(new Person { Name = "Ada", Age = 37 });
Person person = serializer.Deserialize<Person>(json);
By default, object property names serialize as camelCase. To preserve declared member names or apply a different built-in transform:
JsonSerializer serializer = new()
{
PropertyNamingPolicy = JsonNamingPolicy.SnakeLowerCase,
};
This naming policy applies to object property names. Dictionary keys remain unchanged by default. To opt into dictionary key transformation separately:
JsonSerializer serializer = new()
{
DictionaryKeyNamingPolicy = JsonNamingPolicy.CamelCase,
};
To attach a converter directly to a type or member instead of registering it globally:
[JsonConverter(typeof(MyValueConverter))]
public partial class MyValue
{
public string? Name { get; set; }
}
To accept more human-authored JSON during deserialization:
JsonSerializer serializer = new()
{
AllowTrailingCommas = true,
ReadCommentHandling = JsonCommentHandling.Skip,
};
To retain and re-emit JSON properties that your type does not model yet:
[GenerateShape]
public partial class Person
{
public string? Name { get; set; }
[JsonExtensionData]
public Dictionary<string, string>? ExtensionData { get; set; }
}
Changes from Previous Version
Adoption Assessment
A verified publisher signal is available. Assess fit from the package's supported frameworks, license and dependency graph rather than popularity alone.
Related Guides & Workflows
Learn how to evaluate, integrate, or audit this package in your .NET project.