BbQ.Outcome.SystemTextJson 1.2.0-preview.2

This is a prerelease version of BbQ.Outcome.SystemTextJson.
dotnet add package BbQ.Outcome.SystemTextJson --version 1.2.0-preview.2
                    
NuGet\Install-Package BbQ.Outcome.SystemTextJson -Version 1.2.0-preview.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="BbQ.Outcome.SystemTextJson" Version="1.2.0-preview.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="BbQ.Outcome.SystemTextJson" Version="1.2.0-preview.2" />
                    
Directory.Packages.props
<PackageReference Include="BbQ.Outcome.SystemTextJson" />
                    
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 BbQ.Outcome.SystemTextJson --version 1.2.0-preview.2
                    
#r "nuget: BbQ.Outcome.SystemTextJson, 1.2.0-preview.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 BbQ.Outcome.SystemTextJson@1.2.0-preview.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=BbQ.Outcome.SystemTextJson&version=1.2.0-preview.2&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=BbQ.Outcome.SystemTextJson&version=1.2.0-preview.2&prerelease
                    
Install as a Cake Tool

BbQ.Outcome.SystemTextJson

Optional, explicit System.Text.Json converters for .NET 8, 9, and 10. No JSON dependency is introduced into the core Outcome project. Closed converters consume JsonTypeInfo<T> rather than creating types or searching assemblies at runtime.

Installation

This package ships with the Outcome family under the same outcome-v* version.

dotnet add package BbQ.Outcome.SystemTextJson --prerelease

Wire format

Typed success: {"isSuccess":true,"value":42}

Typed failure: {"isSuccess":false,"errors":[{"code":"MISSING","message":"Not found"}]}

Only the active branch is serialized. A null successful value is allowed when the value type supports it. Null outcomes, default/uninitialized outcomes, missing or nonboolean flags, duplicate or unknown envelope fields, contradictory branches, empty errors, and null error entries are rejected. Reading malformed envelopes throws JsonException; serializing an uninitialized outcome throws the core InvalidOperationException.

The envelope is deliberately strict and case-sensitive. Customize its three names with OutcomeJsonEnvelope; they must be nonblank and distinct. Payload naming, enum representation, and custom payload conversion are determined by the supplied payload metadata, not implicitly inherited from the outer serializer options. Changes to envelope names or error type identifiers require an application-level wire-contract migration.

Registration and Native AOT

var payload = WireContext.Default;
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);
options.AddOutcomeConverter(payload.User, payload.AppError);
var wire = new WireContext(options);

string json = JsonSerializer.Serialize(outcome, wire.UserOutcome);
var restored = JsonSerializer.Deserialize(json, wire.UserOutcome);

[JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata,
    PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]
[JsonSerializable(typeof(User))]
[JsonSerializable(typeof(AppError))]
[JsonSerializable(typeof(Outcome<User, AppError>), TypeInfoPropertyName = "UserOutcome")]
internal partial class WireContext : JsonSerializerContext { }

Include each closed Outcome root in the source-generated context, register its converter on fresh options, and create the context with those options. Supply the root metadata to serialize/deserialize calls. There is no reflection-based open-generic factory. The samples/BbQ.Outcome.AotSmoke project verifies both Outcome forms with reflection disabled and a real Native AOT publish/run.

Heterogeneous error allowlist

var registry = new OutcomeErrorTypeRegistryBuilder()
    .Register("app-error-v1", payload.AppError)
    .Register("text-v1", payload.String)
    .Build();
options.AddOutcomeConverter(payload.User, registry);

A heterogeneous failure uses an explicit tagged error envelope:

{"isSuccess":false,"errors":[
  {"type":"app-error-v1","error":{"code":"MISSING","message":"Not found"}},
  {"type":"text-v1","error":"Another error"}
]}

Unknown identifiers, missing/null payloads, and duplicate or extra tag-envelope fields are rejected. Writing an unregistered exact runtime type throws NotSupportedException. Registering duplicate types or identifiers throws. A registry is an immutable snapshot of its builder; callers cannot mutate an active registry. It never calls Type.GetType, loads an assembly, or trusts a CLR type name from JSON. Explicitly supplied payload converters remain application-owned and must themselves be safe for untrusted input and compatible with trimming/AOT when required.

Scope

These converters define a storage/message wire contract, not a public API exposure policy. Use the separate ASP.NET Core adapter for status mapping and redacted Problem Details. The converters buffer one outcome with JsonDocument; enforce request/message size limits at the application boundary. Generic payload object graphs follow System.Text.Json depth limits and the provided metadata's validation semantics.

Product Compatible and additional computed target framework versions.
.NET 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 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. 
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.2.0-preview.2 32 9/13/2026
1.2.0-preview.1 44 9/13/2026