CSharpEssentials.Json
6.5.1
See the version list below for details.
dotnet add package CSharpEssentials.Json --version 6.5.1
NuGet\Install-Package CSharpEssentials.Json -Version 6.5.1
<PackageReference Include="CSharpEssentials.Json" Version="6.5.1" />
<PackageVersion Include="CSharpEssentials.Json" Version="6.5.1" />
<PackageReference Include="CSharpEssentials.Json" />
paket add CSharpEssentials.Json --version 6.5.1
#r "nuget: CSharpEssentials.Json, 6.5.1"
#:package CSharpEssentials.Json@6.5.1
#addin nuget:?package=CSharpEssentials.Json&version=6.5.1
#tool nuget:?package=CSharpEssentials.Json&version=6.5.1
CSharpEssentials.Json
Enhanced JSON serialization utilities on top of System.Text.Json.
Features
- Enum Conventions:
[StringEnum]enums read and write their wire names (AddEnumConventions); other enums keep the host's behavior. - Multi-Format DateTime: Read
DateTimeandDateTime?from many date formats automatically. - Polymorphic Serialization: Serialize abstract types and interfaces with a
$typediscriminator. - Pre-Configured Options: CamelCase, ignore cycles, ignore nulls, relaxed escaping, plus a strict preset.
- JsonElement Helpers:
ToClrObjectturns aJsonElementinto plain CLR values.
Installation
dotnet add package CSharpEssentials.Json
Targets net11.0, net10.0, net9.0 and netstandard2.1. It depends on CSharpEssentials.Enums.
Usage
Pre-Configured Options
using CSharpEssentials.Json;
using System.Text.Json;
var options = EnhancedJsonSerializerOptions.DefaultOptions;
string json = JsonSerializer.Serialize(myObject, options);
| Member | Contents |
|---|---|
DefaultOptionsWithoutConverters |
Web defaults, camelCase, case-insensitive reads, nulls ignored on write, ReferenceHandler.IgnoreCycles, relaxed escaping |
DefaultOptions |
The above plus enum conventions (Data mode), MultiFormatDateTimeConverterFactory and PolymorphicJsonConverterFactory |
DefaultOptionsWithDateTimeConverter |
DefaultOptionsWithoutConverters plus MultiFormatDateTimeConverterFactory |
StrictOptions |
Case-sensitive; rejects trailing commas, comments and unmapped members |
CreateOptionsWithConverters(params JsonConverter[]) |
DefaultOptionsWithoutConverters plus the given converters |
options.Create(configure) |
Copies the options and applies configure to the copy |
source.ApplyTo(target) / target.ApplyFrom(source) |
Copies settings and converters onto another instance; the target keeps its own TypeInfoResolver when the source has none |
The preset instances are shared and become read-only after first use, so call Create to get a modifiable copy. EnhancedJsonSerializerOptions is annotated [RequiresUnreferencedCode] and [RequiresDynamicCode] because DefaultOptions includes the reflection-based polymorphic converter.
JsonSerializerOptions indented = EnhancedJsonSerializerOptions.DefaultOptions.Create(o => o.WriteIndented = true);
var target = new JsonSerializerOptions();
EnhancedJsonSerializerOptions.DefaultOptions.ApplyTo(target);
Quick Extensions
ConvertToJson, ConvertFromJson and ConvertToJsonDocument<T> use EnhancedJsonSerializerOptions.DefaultOptions (or the options you pass) through reflection-based serialization. They are annotated [RequiresUnreferencedCode] and [RequiresDynamicCode]; in trimmed or NativeAOT apps call JsonSerializer with a JsonSerializerContext instead.
using System.Text.Json;
using CSharpEssentials.Json;
var user = new User("Alice", 30);
string json = user.ConvertToJson(); // {"name":"Alice","age":30}
User? parsed = json.ConvertFromJson<User>();
object? untyped = json.ConvertFromJson(typeof(User));
JsonDocument doc = json.ConvertToJsonDocument();
public record User(string Name, int Age);
ConvertToJsonDocument() on a string takes no options: it parses the text as JSON, and text that is not valid JSON becomes a JSON string value in the document. It returns null only when every strategy fails. ConvertToJsonDocument<T>(options) on any other value serializes it to a document.
JsonElement to CLR Values
Dictionary<string, object> and object deserialize to JsonElement. ToClrObject turns them into plain values: objects become Dictionary<string, object?>, arrays List<object?>, numbers int, long, decimal or double (first that fits).
using System.Text.Json;
using CSharpEssentials.Json;
using JsonDocument doc = JsonDocument.Parse("""{"id":1,"price":9.99,"tags":["a"]}""");
var data = (Dictionary<string, object?>)doc.RootElement.ToClrObject()!;
// data["id"] is int, data["price"] is decimal, data["tags"] is List<object?>
Enum Conventions
AddEnumConventions adds the enum converter for every enum with generated metadata ([StringEnum], see CSharpEssentials.Enums). Other enums are left to the converters already on the options, so a plain enum stays a number unless you add JsonStringEnumConverter yourself.
using System.Text.Json;
using CSharpEssentials.Enums;
using CSharpEssentials.Json;
[StringEnum]
public enum Status { Active, Inactive, [EnumFallback] Unknown }
public enum Level { Low, High }
public sealed record Account(Status Status, Level Level);
// Data mode (the default): tolerant, for values you stored or received from a trusted service
JsonSerializerOptions data = new JsonSerializerOptions(JsonSerializerDefaults.Web)
.AddEnumConventions(EnumConventions.Default);
// Input mode: strict, for request bodies (AddEnumConventions() in CSharpEssentials.AspNetCore does this for you)
JsonSerializerOptions input = new JsonSerializerOptions(JsonSerializerDefaults.Web)
.AddEnumConventions(EnumConventions.Default, EnumReadMode.Input);
JsonSerializer.Serialize(new Account(Status.Active, Level.High), data); // {"status":"active","level":1}
JsonSerializer.Deserialize<Account>("""{"status":"gone","level":0}""", data); // Status.Unknown (fallback)
JsonSerializer.Deserialize<Account>("""{"status":"gone","level":0}""", input); // throws EnumValueJsonException
- Reads accept the wire name, the member name in any casing, aliases and the number of a defined member.
Inputmode appliesEnumConventions.AcceptNumbers,AcceptMemberNamesandCaseInsensitive. - Undefined values (
"gone",999) are rejected withEnumValueJsonException(aJsonExceptionwhoseErrorproperty carries theEnumValueError). InDatamode only, they map to the[EnumFallback]member when the enum declares one (EnumConventions.UnknownValue = UnknownEnumValueHandling.UseFallback, the default). - Writes are the wire name, or the number with
writeAs: EnumWireFormat.Number.[Flags]values are JSON arrays. EnhancedJsonSerializerOptions.DefaultOptionsalready callsAddEnumConventions(EnumConventions.Default)(Data mode).- A
[StringEnum]enum without generated metadata (CSE0015) throws when its converter is created instead of falling back to numbers.AddEnumConventionsWithReflectionalso converts enums without metadata through reflection; it is not trim or AOT safe.
ConditionalStringEnumConverter (4.x) is obsolete and forwards to the same converter in Input mode. It no longer has AllowUndefinedValues: undefined numbers are always rejected. See Migrating from 4.x to 5.0.
StringEnumNaming
StringEnumNaming is obsolete in 5.0 and stays as a working facade over EnumMetadata. In new code use EnumMetadata, EnumValueFormatter, EnumValueParser or the generated ToWireName() and TryParseWire helpers: they are the naming source that JSON, EF Core storage, Swagger schemas and query/route binding all use, so a member is spelled the same everywhere. Names are [JsonStringEnumMemberName] when present, otherwise snake_case_lower.
using CSharpEssentials.Enums;
using CSharpEssentials.Json;
[StringEnum]
public enum Http { OK, HTTPStatus }
StringEnumNaming.GetName(Http.HTTPStatus); // "http_status"
StringEnumNaming.GetNames<Http>(); // ["ok", "http_status"]
StringEnumNaming.TryParse<Http>("HTTPStatus", out var value); // true (policy name, member name or number)
Polymorphic Serialization
namespace Zoo;
public abstract class Animal { public string Name { get; set; } = string.Empty; }
public class Dog : Animal { public string Breed { get; set; } = string.Empty; }
using Zoo;
Animal dog = new Dog { Name = "Rex", Breed = "Labrador" };
string json = dog.ConvertToJson(); // {"$type":"Zoo.Dog","breed":"Labrador","name":"Rex"}
Animal? restored = json.ConvertFromJson<Animal>();
DefaultOptions applies PolymorphicJsonConverterFactory to abstract classes and interfaces; collections and dictionaries keep the built-in array and object serialization. The $type value is the concrete type's full name (namespace included) and is written first. On read, $type is required and is matched against the non-abstract types of the loaded assemblies that derive from the declared type; a missing or unknown value throws JsonException. Discovery uses reflection, so this is not trim or AOT safe: use [JsonPolymorphic] with source generation there.
Multi-Format DateTime
MultiFormatDateTimeConverterFactory (part of DefaultOptions and DefaultOptionsWithDateTimeConverter) reads DateTime and DateTime? from JSON strings in ISO 8601 (with or without Z or an offset), yyyy-MM-dd, dd.MM.yyyy, dd/MM/yyyy, MM/dd/yyyy, March 14, 2024, 14 March 2024, yyyyMMdd, RFC 1123 (Thu, 14 Mar 2024 15:30:45 GMT) and other patterns, and from a numeric string of Unix seconds. Unrecognized text throws JsonException listing the supported formats; null is allowed only for DateTime?. Values are written as yyyy-MM-ddTHH:mm:ss.ffffffzzz.
string[] dates = ["\"2024-03-14T15:30:45Z\"", "\"14.03.2024\"", "\"March 14, 2024\""];
foreach (var d in dates)
{
DateTime dt = d.ConvertFromJson<DateTime>();
}
var options = new JsonSerializerOptions();
options.Converters.Add(new MultiFormatDateTimeConverterFactory("dd.MM.yyyy HH-mm"));
DateTime custom = JsonSerializer.Deserialize<DateTime>("\"14.03.2024 10-20\"", options);
Constructor arguments add formats to the built-in list. Every value is returned as UTC (DateTime.Kind is Utc) regardless of the host time zone: input without an offset is read as UTC, input with an offset or Z is converted to UTC, and a Unix-seconds string becomes the matching UTC instant. A date-only value such as "14.03.2024" is midnight UTC on that date. Slash dates are tried as dd/MM/yyyy before MM/dd/yyyy, so "03/04/2024" reads as 3 April.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. 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 is compatible. 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. net11.0 is compatible. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- CSharpEssentials.Enums (>= 6.5.1)
- System.Text.Json (>= 9.0.4)
-
net10.0
- CSharpEssentials.Enums (>= 6.5.1)
-
net11.0
- CSharpEssentials.Enums (>= 6.5.1)
-
net9.0
- CSharpEssentials.Enums (>= 6.5.1)
NuGet packages (7)
Showing the top 5 NuGet packages that depend on CSharpEssentials.Json:
| Package | Downloads |
|---|---|
|
CSharpEssentials.Results
Result pattern implementation for functional error handling in C#. Provides Result<T> and Result types for railway-oriented programming, eliminating exceptions for expected failures. Foundation for functional programming patterns and robust error handling. |
|
|
CSharpEssentials
A comprehensive C# library enhancing functional programming capabilities with type-safe monads (Maybe, Result), discriminated unions (Any), and robust error handling. Features include: domain-driven design support, enhanced Entity Framework integration, testable time management, JSON utilities, and LINQ extensions. Built for modern C# development with focus on maintainability, testability, and functional programming principles. |
|
|
CSharpEssentials.EntityFrameworkCore
Enhances Entity Framework Core with functional programming patterns and DDD-friendly features. Includes base entity classes, soft delete support, audit trails, query filters, optimistic concurrency, PostgreSQL integration, query performance monitoring, and domain event handling. Perfect for building maintainable and scalable data access layers in modern .NET applications. |
|
|
CSharpEssentials.AspNetCore
A comprehensive ASP.NET Core library that enhances functional programming capabilities in web applications. Features include API versioning, global exception handling with enhanced problem details, enum binding and wire formats, model validation, optimized JSON handling, and seamless integration with CSharpEssentials core functional patterns (Result, Maybe, Rule Engine). Perfect for building robust, maintainable, and type-safe web APIs following functional programming principles. OpenAPI documents come from CSharpEssentials.AspNetCore.OpenApi or CSharpEssentials.AspNetCore.Swashbuckle. |
|
|
CSharpEssentials.Any
Discriminated union types (Any<T0,T1> to Any<T0,...,T7>) for functional programming in C#. Provides type-safe alternatives to object/dynamic with pattern matching, implicit conversions, and JSON serialization support. Essential for functional programming patterns and type-safe handling of multiple possible types. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 6.5.2 | 374 | 10/10/2026 |
| 6.5.1 | 378 | 10/10/2026 |
| 6.5.0 | 378 | 10/9/2026 |
| 6.4.0 | 387 | 10/9/2026 |
| 6.3.0 | 407 | 10/8/2026 |
| 6.2.0 | 452 | 10/8/2026 |
| 6.1.0 | 445 | 10/7/2026 |
| 6.0.0 | 462 | 10/7/2026 |
| 5.2.1 | 470 | 10/7/2026 |
| 5.2.0 | 460 | 10/7/2026 |
| 5.1.0 | 484 | 10/7/2026 |
| 5.0.0 | 482 | 10/6/2026 |
| 4.1.0 | 456 | 10/6/2026 |
| 4.0.0 | 460 | 10/5/2026 |
| 3.2.3 | 622 | 5/31/2026 |
| 3.2.2 | 510 | 5/31/2026 |
| 3.2.1 | 486 | 5/31/2026 |
| 3.2.0 | 482 | 5/30/2026 |
| 3.1.0 | 475 | 5/27/2026 |
| 3.0.8 | 458 | 5/20/2026 |