SnowBank.Serialization.Json.CodeGen 7.3.2

dotnet add package SnowBank.Serialization.Json.CodeGen --version 7.3.2
                    
NuGet\Install-Package SnowBank.Serialization.Json.CodeGen -Version 7.3.2
                    
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="SnowBank.Serialization.Json.CodeGen" Version="7.3.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SnowBank.Serialization.Json.CodeGen" Version="7.3.2" />
                    
Directory.Packages.props
<PackageReference Include="SnowBank.Serialization.Json.CodeGen" />
                    
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 SnowBank.Serialization.Json.CodeGen --version 7.3.2
                    
#r "nuget: SnowBank.Serialization.Json.CodeGen, 7.3.2"
                    
#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 SnowBank.Serialization.Json.CodeGen@7.3.2
                    
#: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=SnowBank.Serialization.Json.CodeGen&version=7.3.2
                    
Install as a Cake Addin
#tool nuget:?package=SnowBank.Serialization.Json.CodeGen&version=7.3.2
                    
Install as a Cake Tool

SnowBank SDK - JSON Source Code Generator

Generates code for custom JSON converters and proxies

This package contains a source code generator that will output optimized code for application types.

  • Containers: application can define a container type and a set of top-level application types (records, structs, ...) that are exchanged with other processes as JSON.
  • Converters: generates custom implements of IJsonConverter<...> for all the types in the dependency graph. Each converter can serialize, pack and unpack instances of these types, without relying on reflection at runtime.
  • Proxies: generates a set of ReadOnly and Writable proxies, that expose an underlying JSON Object as a type-safe object with the same properties and types as the parent type, without having to deserialize all the properties.

How to reference

Via NuGet, simply add a PackageReference to any project that contains your application types.

Via a git sub-module, add a ProjectReference and flag it as a source analyzer.

<ProjectReference
	Include="..\_PATH_TO_MODULE_\SnowBank.Serialization.Json.CodeGen\SnowBank.Serialization.Json.CodeGen.csproj"
	OutputItemType="Analyzer"
	ReferenceOutputAssembly="false" />

This package will only be used at build time, and should not be redistributed with the rest of tha application.

How to use

Containers

In the shared assembly that contains most of your "data" types, simply create a new static class that will act as a container, decorate it with [CrystalJsonConverter], and then add as many [CrystalJsonSerializable(typeof(...)] as you have top-level data types.

The converter will walk the type dependency graph from all these types, and generate custom converters and proxies for each one. You don't need to mention any nested type or types references by properties, as they should automatically be included.

	[CrystalJsonConverter]
	[CrystalJsonSerializable(typeof(User))]
	[CrystalJsonSerializable(typeof(Order))]
	[CrystalJsonSerializable(typeof(Product))]
	[CrystalJsonSerializable(typeof(Role))]
	// and any other main types
	public static partial class MyAppConverters
	{

	}

This will generate a nested type for each of these types T, that will generate multiple types with the following suffix:

  • (TypeName)Converter: implement a IJsonConverter<T> and provides the Serialize(...), Pack(...) and Unpack(...) methods
  • (TypeName)ReadOnly: read-only struct that implements IJsonReadOnlyProxy<...>
  • (TypeName)ReadOnly: mutable class that implements IJsonWritableProxy<...>

Examples

Example: how to serialize a type into a JSON literal (text, bytes, ...):

// generate the instance that you need to serialize into JSON...
User result = MethodThatReturnsUser();

// serialize into a string:
string jsonText = MyAppConverters.User.ToJson(result);

// serialize into a Slice:
Slice jsonBytes = MyAppConverters.User.ToJsonSlice(result);

// serialize into a byte[] array:
Slice jsonBytes = MyAppConverters.User.ToJsonBytes(result);

Example: how to pack a type into a JSON Object (DOM):

// generate the instance that you need to serialize into JSON...
User result = MethodThatReturnsUser();

JsonValue json = MyAppConverters.User.Pack(result);
Console.WriteLine($"- Id: {json["id"]}");
Console.WriteLine($"- FirstName: {json["firstName"]}");
Console.WriteLine($"- LastName: {json["lastName"]}");

Example: how to unpack a JSON Object back into an instance of the original type:

JsonObject obj = new();
obj["id"] = "ag007"";
obj["firstName"] = "James";
obj["lastName"] = "Bond";
// ...

Person person = MyAppConverters.User.Unpack(obj);
Console.WriteLine($"- Id: {person.Id}");
Console.WriteLine($"- FirstName: {person.FirstName}");
Console.WriteLine($"- LastName: {person.LastName}");

Example: how to work with a read-only proxy for a type:

JsonObject obj = new();
obj["id"] = "ag007";
obj["firstName"] = "James";
obj["lastName"] = "Bond";
// ...

var person = MyAppConverters.User.ToReadOnly(obj);
Console.WriteLine($"- Id: {person.Id}");
Console.WriteLine($"- FirstName: {person.FirstName}");
Console.WriteLine($"- LastName: {person.LastName}");

Observe that the read-only proxy looks identical to the original type, and note that it will only deserialize the value of a field only when it is accessed

Example: how to work with a writable proxy for a type:

JsonObject obj = new();
// ...

var person = MyAppConverters.User.ToWritable(obj);
person.Id = "ag007";
person.FirstName = "James";
person.LastName = "Bond";

Console.WriteLine($"- Id: {obj["id"]}");
Console.WriteLine($"- FirstName: {obj["firstName"]}");
Console.WriteLine($"- LastName: {obj["lastName"]}");

Observe that the writable proxy looks identical to the original type, and note that it will only touch the properties that are updated, without changing any other fields in the existing JSON object

Example: how to get a ICrystalJsonTypeResolver that will use the generated converters for all the known types in the container.

public static T Decode<T>(JsonObject obj)
{

	// this returns a resolver that will map all the application types in the container to the generated converters
	var resolver = MyAppConverters.GetResolver();

	// get a converter for a known type:
	if (!resolver.TryGetConverterFor<Person>(out var personConverter))
	{
		throw new InvalidOperationException("Type not supported");
	}

	// use the converter to deserialize a T instance
	return personConverter.Unpack(obj);
}

var obj = new JsonObject() { ["id"] = "ag007", ["firstName"] = "James", ["lastName"] = "Bond" };
var person = Decode<Person>(obj);
Console.WriteLine($"- Id: {person.Id}");
Console.WriteLine($"- FirstName: {person.FirstName}");
Console.WriteLine($"- LastName: {person.LastName}");
There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.