Nexus and JSON

Nexus uses JSON heavily for serialization of different data structures. In v1 of Nexus the default serialization used Newtonsoft.Json but since v2 the default is System.Text.Json instead.

If you're using Newtonsoft.Json you can install the package CommerceMind.Nexus.NewtonsoftJson and call builder.Services.AddNexus().AddNewtonsoftJson() to use Newtonsoft.Json for serialization instead of System.Text.Json.

Customizing the serialization

Both System.Text.Json and Newtonsoft.Json allows you to add custom converters, but System.Text.Json doesn't allow you to modify the global serialization options.

In Nexus all of the serialization is controlled by the different serialization interfaces, except for the response data in the API. Nexus passes object instances to ASP.NET which then handles the serialization. Nexus will however still control the serialization of queue messages inside the API models. Which mean that you might get a response looking like this:

{
  "id": 4823771,
  "status": "Processed",
  "retryCount": 0,
  "message": {
    "Id": null,
    "SomeProperty": null,
    "ExampleEnum": "Value1"
  }
}

Where the outer object has gotten kebabCased by ASP.NETs JSON formatting rules but the message object is PascalCased because that's the default formatting in Nexus.

Similar to ASP.NET there's also a hook to modify the Nexus serialization:

builder.Services.AddNexus().ConfigureJsonOptions(options =>
{
    options.SerializerOptions.Converters.Add(new MyCustomConverter());
});

Dealing with interfaces and abstract types in serialization

Sometimes Nexus needs to deal with serializing to and from abstract types such as interfaces or abstract classes. In those cases Nexus will serialize a .NET type name into the JSON structure so the deserialization later on will know which type to deserialize to. Note that Nexus never does this on input from data coming in through the API, only on data that Nexus itself has serialized and stored in the database.

This works just like Newtonsoft.Jsons TypeNameHandling. Since there are security implications in this Nexus also includes a hash of the type name in the serialized JSON which is then verified before loading the type during deserialization.

You can control this with the following configuration:

builder.Services.AddNexus().ConfigureJsonOptions(options =>
{
    // The salt used when hashing types
    options.TypeHashSalt = "mysalt";
    // If a $typehash property should be included or not in the JSON. Including a type hash
    // makes the serialized JSON incompatible with Newtonsoft.Json which you might want to keep
    // compatibility with.
    options.WriteTypeHash = false;
    // If Nexus should reject any JSON with a $type but without a $typehash
    options.RequireTypeHash = true;
});

You're able to even further control this with the interfaces ISerializationBinder and ISerializationTypeHashCalculator. The ISerializationBinder interface is what reads and writes a .NET type to it's string representation and works just like the standard .NET [ISerializationBinder](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.serialization.serializationbinder?view=net-8.0).ISerializationTypeHashCalculatoris responsible for creating a hash for a type name. If you ever want to change the type hash salt you need to implement your ownISerializationTypeHashCalculator` to handle both the new and old salt until no data is using the old salt anymore.