EnumCraft.Json 1.0.1

dotnet add package EnumCraft.Json --version 1.0.1
                    
NuGet\Install-Package EnumCraft.Json -Version 1.0.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="EnumCraft.Json" Version="1.0.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="EnumCraft.Json" Version="1.0.1" />
                    
Directory.Packages.props
<PackageReference Include="EnumCraft.Json" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add EnumCraft.Json --version 1.0.1
                    
#r "nuget: EnumCraft.Json, 1.0.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package EnumCraft.Json@1.0.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=EnumCraft.Json&version=1.0.1
                    
Install as a Cake Addin
#tool nuget:?package=EnumCraft.Json&version=1.0.1
                    
Install as a Cake Tool

EnumCraft.Json

JSON serialization extensions for EnumCraft TypedEnum and TypedFlag instances

NuGet License: MIT

What is EnumCraft.Json?

A lightweight JSON serialization extension package for EnumCraft.Core that provides clean, structured JSON output for TypedEnum and TypedFlag instances.

✅ Simple JSON serialization for TypedEnum
✅ Enhanced serialization for TypedFlag with decomposed flags array
✅ Customizable output with JsonSerializerOptions
✅ Zero configuration — just add the package and use the extensions
✅ Multi-targeted — Works with .NET Framework 4.7.2+ and .NET 8+


Installation

dotnet add package EnumCraft.Core
dotnet add package EnumCraft.Json

Quick Start

TypedEnum Serialization

using EnumCraft;
using EnumCraft.Json;

public class DocumentType : TypedEnumInt<DocumentType>
{
    public static readonly DocumentType Invoice       = new(1, "Invoice",        nameof(Invoice));
    public static readonly DocumentType PurchaseOrder = new(2, "Purchase Order", nameof(PurchaseOrder));
    public static readonly DocumentType CreditMemo    = new(3, "Credit Memo",    nameof(CreditMemo));

    private DocumentType(int id, string description, string code)
      : base(id, description, code) { }
}

// Serialize to object
var type    = DocumentType.Invoice;
var jsonObj = type.AsJsonObject();
// Returns: { id = 1, description = "Invoice", code = "Invoice" }

// Serialize to JSON string
string json = type.AsJsonString();
// Returns: {"id":1,"description":"Invoice","code":"Invoice"}

// With formatting
var options    = new JsonSerializerOptions { WriteIndented = true };
string prettyJson = type.AsJsonString(options);

TypedFlag Serialization

using EnumCraft;
using EnumCraft.Json;

public class Permissions : TypedFlagInt<Permissions>
{
    public static readonly Permissions None    = new(0, "None",    nameof(None));
    public static readonly Permissions Read    = new(1, "Read",    nameof(Read));
    public static readonly Permissions Write   = new(2, "Write",   nameof(Write));
    public static readonly Permissions Execute = new(4, "Execute", nameof(Execute));
    public static readonly Permissions All     = new(7, "All",     nameof(All));

    private Permissions(int id, string description, string code)
      : base(id, description, code) { }
}

// Single flag
var read    = Permissions.Read;
var jsonObj = read.ToJsonObject();
// Returns: { id = 1, description = "Read", code = "Read" }

// Combined flags - includes decomposed flags array
var readWrite    = Permissions.Read | Permissions.Write;
var combinedObj  = readWrite.ToJsonObject();
// Returns:
// {
//   id = 3,
//   description = "Read, Write",
//   code = "Read | Write",
//   flags = [
//     { id = 1, description = "Read", code = "Read" },
//     { id = 2, description = "Write", code = "Write" }
//   ]
// }

// Serialize to JSON string
string json = readWrite.ToJsonString();

API Reference

TypedEnum Extensions

Available on all ITypedEnum<TSelf, TId> instances:

AsJsonObject()
object AsJsonObject<TSelf, TId>(this ITypedEnum<TSelf, TId> typedEnum)

Returns an anonymous object with id, description, and code properties.

Example:

var obj = DocumentType.Invoice.AsJsonObject();
// { id = 1, description = "Invoice", code = "Invoice" }
AsJsonString()
string AsJsonString<TSelf, TId>(this ITypedEnum<TSelf, TId> typedEnum, JsonSerializerOptions? options = null)

Returns a JSON string representation.

Example:

var json = DocumentType.Invoice.AsJsonString();
// {"id":1,"description":"Invoice","code":"Invoice"}

var options   = new JsonSerializerOptions { WriteIndented = true };
var prettyJson = DocumentType.Invoice.AsJsonString(options);

TypedFlag Extensions

Available on all TypedFlag instances — use different method names than TypedEnum to avoid constraint conflicts:

ToJsonObject()
object ToJsonObject<TSelf, TId>(this ITypedEnum<TSelf, TId> typedEnum)

Returns an anonymous object with id, description, and code properties. For combined flags, includes a flags array with decomposed flag objects.

Example — Single Flag:

var obj = Permissions.Read.ToJsonObject();
// { id = 1, description = "Read", code = "Read" }

Example — Combined Flags:

var combo = Permissions.Read | Permissions.Write | Permissions.Execute;
var obj   = combo.ToJsonObject();
// {
//   id = 7,
//   description = "Read, Write, Execute",
//   code = "Read | Write | Execute",
//   flags = [
//     { id = 1, description = "Read", code = "Read" },
//     { id = 2, description = "Write", code = "Write" },
//     { id = 4, description = "Execute", code = "Execute" }
//   ]
// }
ToJsonString()
string ToJsonString<TSelf, TId>(this ITypedEnum<TSelf, TId> typedEnum, JsonSerializerOptions? options = null)

Returns a JSON string representation with flags array for combined flags.

Example:

var combo = Permissions.Read | Permissions.Write;
var json  = combo.ToJsonString();
// {"id":3,"description":"Read, Write","code":"Read | Write","flags":[...]}

Method Names: Why Different?

TypedEnum uses: AsJsonObject() and AsJsonString()
TypedFlag uses: ToJsonObject() and ToJsonString()

Due to .NET Standard 2.0 compatibility constraints with IBitwiseOperators, TypedFlag extensions cannot share the same method names as TypedEnum extensions without causing compilation issues. The different names make the distinction explicit:

  • For TypedEnum → use As... methods
  • For TypedFlag → use To... methods

Advanced Usage

Custom JSON Options

var options = new JsonSerializerOptions{ WriteIndented        = true,
                                         PropertyNamingPolicy = JsonNamingPolicy.CamelCase };

var json = DocumentType.Invoice.AsJsonString(options);

Using in APIs

[HttpGet("document-types/{id}")]
public IActionResult GetDocumentType(int id)
{
    var type    = DocumentType.GetByID(id);
    var jsonObj = type.AsJsonObject();

    return Ok(jsonObj);
}

[HttpGet("permissions")]
public IActionResult GetPermissions()
{
    var userPerms = Permissions.Read | Permissions.Write;
    var jsonObj   = userPerms.ToJsonObject();

    return Ok(jsonObj);
}

Serializing Collections

var allTypes  = DocumentType.GetAll();
var jsonArray = allTypes.Select(t => t.AsJsonObject()).ToArray();
var json      = JsonSerializer.Serialize(jsonArray);

Logging

var type = DocumentType.Invoice;
_logger.LogInformation("Document type resolved: {Type}", type.AsJsonString());

Best Practices

✅ DO

  • Use AsJsonObject() when you need the object for further manipulation
  • Use AsJsonString() when you need the final JSON string
  • Use ToJsonObject() / ToJsonString() for TypedFlags to get the flags array
  • Reuse JsonSerializerOptions instances for performance

❌ DON'T

  • Mix As... and To... methods - use As... for TypedEnum, To... for TypedFlag
  • Serialize TypedEnum or TypedFlag directly with JsonSerializer.Serialize() - you lose the structured output

Troubleshooting

"Method not found" errors

Make sure you have the correct using directive at the top of your file:

using EnumCraft.Json;

TypedFlag doesn't show flags array

Make sure you're using ToJsonObject() / ToJsonString() - not AsJson...:

// ❌ Wrong — won't include flags array
var json = myFlag.AsJsonString();

// ✅ Correct — includes flags array
var json = myFlag.ToJsonString();

Known Limitations

Additional Properties Not Serialized

AsJsonObject(), AsJsonString(), ToJsonObject(), and ToJsonString() serialize only the base id, description, and code properties. Any additional properties defined on a concrete type are silently ignored.

public class DocumentType : TypedEnumInt<DocumentType>
{
    public bool IsActive { get; }  // ← will NOT appear in JSON output
    // ...
}

DocumentType.Invoice.AsJsonString();
// {"id":1,"description":"Invoice","code":"Invoice"} — IsActive is not included

This is a known limitation - a future release will add a virtual ToJsonProperties() method that concrete types can override to include additional properties in the serialized output.


Framework Support

Framework Supported
.NET Framework 4.7.2+ ✅
.NET Standard 2.0+ ✅
.NET 8+ ✅

Dependencies

  • EnumCraft.Core (v1.0.0 or later)
  • System.Text.Json (v4.7.2 or later)
  • Microsoft.CSharp (v4.7.0 or later) - required for .NET Standard 2.0 dynamic support


License

MIT — see LICENSE for details.


Author

Randel Bjorkquist — GitHub | NuGet

Product 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 is compatible.  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 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.1 145 4/26/2026
1.0.0 121 4/26/2026
0.3.1-preview 120 4/22/2026
0.3.0-preview 118 4/20/2026
0.2.2-preview 133 4/6/2026
0.2.1-preview 137 3/2/2026
0.2.0-preview 125 2/24/2026
0.1.4-preview 132 2/22/2026
0.1.3-preview 138 2/19/2026
0.1.0-preview 138 2/17/2026