Codebelt

Savvyio.Extensions.DependencyInjection.Text.Json

Register a System.Text.Json-backed Savvy I/O marshaller in Microsoft DI with configurable formatting and service lifetime.

.NET 10.0 / .NET 9.0 MIT v5.0.8 2,387 downloads

Overview

Savvyio.Extensions.DependencyInjection.Text.Json registers the Savvy I/O JsonMarshaller in IServiceCollection and wires its JsonFormatterOptions into the container. It extends Savvyio.Extensions.DependencyInjection with the built-in JSON implementation from Savvyio.Extensions.Text.Json, so application services can take a JsonMarshaller dependency instead of constructing one inline.

The package is intentionally narrow. It does not introduce a separate serializer or new JSON converters of its own. It composes the existing marshaller and configured formatter options into Microsoft Dependency Injection, defaulting JsonFormatterOptions.Settings.WriteIndented to false when no JSON setup delegate is supplied and defaulting the registration lifetime to ServiceLifetime.Singleton.

Key APIs

AddJsonMarshaller registers JsonMarshaller on an IServiceCollection, applies optional JsonFormatterOptions configuration through the jsonSetup callback, and accepts optional ServiceOptions configuration for the registration itself. The tests cover the null guard, default compact JSON output, custom formatter setup, and a custom scoped lifetime.

JsonMarshaller is the service this package makes available through dependency injection. It comes from Savvyio.Extensions.Text.Json and exposes Serialize and Deserialize methods over streams, so consumers can use one DI-managed marshaller for Savvy I/O messages and other CLR types.

JsonFormatterOptions is the configuration surface forwarded by AddJsonMarshaller. The package registers it in the container and applies o.Settings.WriteIndented = false when no callback is supplied, while custom callbacks can override the underlying built-in JSON formatter settings before the marshaller is resolved.

Basic usage

using System;
using System.IO;
using Codebelt.Extensions.Xunit;
using Cuemon.Extensions.Text.Json.Formatters;
using Microsoft.Extensions.DependencyInjection;
using Savvyio.Extensions.DependencyInjection.Text.Json;
using Savvyio.Extensions.Text.Json;
using Xunit;

namespace MyProject.Tests;

public class JsonMarshallerRegistrationTests : Test
{
    public JsonMarshallerRegistrationTests(ITestOutputHelper output) : base(output) { }

    [Fact]
    public void AddJsonMarshaller_CustomSettings_RegistersMarshaller()
    {
        var services = new ServiceCollection();
        services.AddJsonMarshaller(
            jsonSetup: o => o.Settings.WriteIndented = true,
            serviceSetup: o => o.Lifetime = ServiceLifetime.Scoped);
        services.AddTransient<AuditDocumentWriter>();

        var descriptor = Assert.Single(services, d => d.ServiceType == typeof(JsonMarshaller));
        Assert.Equal(ServiceLifetime.Scoped, descriptor.Lifetime);

        using var provider = services.BuildServiceProvider();
        using var scope = provider.CreateScope();
        var writer = scope.ServiceProvider.GetRequiredService<AuditDocumentWriter>();
        var options = scope.ServiceProvider.GetRequiredService<JsonFormatterOptions>();
        var json = writer.Write(new ShipmentAccepted(Guid.Parse("11111111-1111-1111-1111-111111111111"), "ORD-42"));

        TestOutput.WriteLine(json);

        Assert.True(options.Settings.WriteIndented);
        Assert.Contains('\n', json);
        Assert.Contains("\"orderNumber\": \"ORD-42\"", json);
    }

    private sealed class AuditDocumentWriter(JsonMarshaller marshaller)
    {
        public string Write(ShipmentAccepted entry)
        {
            using var stream = marshaller.Serialize(entry);
            using var reader = new StreamReader(stream);
            return reader.ReadToEnd();
        }
    }

    private sealed record ShipmentAccepted(Guid Id, string OrderNumber);
}

Use this pattern when your application wants one DI-registered JsonMarshaller with centrally managed JSON settings and constructor injection into application services. It matters because the package keeps both the marshaller registration and its formatter options in the container, so callers do not repeat per-call JsonMarshaller construction and setup.

Installation

dotnet add package Savvyio.Extensions.DependencyInjection.Text.Json

Usage guidance

Use this package when the application already depends on IServiceCollection and wants Savvy I/O's built-in JSON marshaller available as a registered service with shared formatter settings. If direct construction of JsonMarshaller is enough, or if you need the Newtonsoft.Json implementation instead, depend on Savvyio.Extensions.Text.Json or Savvyio.Extensions.DependencyInjection.Newtonsoft.Json instead.

Family packages