BbQ.Outcome.SystemTextJson
1.2.0-preview.2
dotnet add package BbQ.Outcome.SystemTextJson --version 1.2.0-preview.2
NuGet\Install-Package BbQ.Outcome.SystemTextJson -Version 1.2.0-preview.2
<PackageReference Include="BbQ.Outcome.SystemTextJson" Version="1.2.0-preview.2" />
<PackageVersion Include="BbQ.Outcome.SystemTextJson" Version="1.2.0-preview.2" />
<PackageReference Include="BbQ.Outcome.SystemTextJson" />
paket add BbQ.Outcome.SystemTextJson --version 1.2.0-preview.2
#r "nuget: BbQ.Outcome.SystemTextJson, 1.2.0-preview.2"
#:package BbQ.Outcome.SystemTextJson@1.2.0-preview.2
#addin nuget:?package=BbQ.Outcome.SystemTextJson&version=1.2.0-preview.2&prerelease
#tool nuget:?package=BbQ.Outcome.SystemTextJson&version=1.2.0-preview.2&prerelease
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 | Versions 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. |
-
net10.0
- BbQ.Outcome (>= 1.2.0-preview.2)
-
net8.0
- BbQ.Outcome (>= 1.2.0-preview.2)
-
net9.0
- BbQ.Outcome (>= 1.2.0-preview.2)
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 |