You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
System.Text.Json ships built-in number converters for every primitive floating-point type plus Half (added in #87994). The remaining built-in floating-point types — System.Numerics.BFloat16 and the IEEE 754 decimal types Decimal32/Decimal64/Decimal128 (#81376) — have no built-in converter. They implement IFloatingPoint<T> exactly like float/double/Half, but today they cannot be (de)serialized as JSON numbers and require a hand-written JsonConverter<T> per type.
Source-generated contexts need a public JsonMetadataServices property per built-in type to emit (JsonMetadataServices.HalfConverter, etc.); there is no such property for these four, so both the reflection and source-gen resolvers fall through to unsupported-type handling.
This proposal adds the four missing properties, completing the built-in floating-point coverage. NFloat is intentionally excluded: it is a platform-dependent alias of float/double, so its JSON representation would vary by platform.
The properties are gated to the target framework where these types are available ($(NetCoreAppCurrent)), matching the existing #if-guarded built-in converter properties.
API Usage
usingSystem.Numerics;usingSystem.Text.Json;publicclassMeasurement{publicBFloat16Weight{get;set;}publicDecimal128Price{get;set;}}varm=newMeasurement{Weight=(BFloat16)1.5f,Price=Decimal128.Parse("19.99")};// Reflection-based: works via the default resolver.stringjson=JsonSerializer.Serialize(m);// {"Weight":1.5,"Price":19.99}Measurementroundtrip=JsonSerializer.Deserialize<Measurement>(json);
Named literals and string number handling behave identically to the other floating-point converters:
Four separate converter types (one per type), mirroring HalfConverter. Rejected in the prototype in favor of a single internal generic converter constrained to IFloatingPointIeee754<T> (the interface exposing the NaN/Infinity members the converter needs) — all four types share the same parse/format/named-literal logic, so four near-identical files would be pure duplication. This is an implementation detail; the public surface is the four properties above either way.
Include NFloat. Rejected: NFloat is a platform-dependent alias, so serializing it as a JSON number produces platform-dependent output.
Risks
Adds four entries to the built-in simple-converter set, a small code-size/metadata increase for reflection and trimming scenarios on the target TFM. No binary or source breaking changes — these are pure additions gated behind the TFM where the underlying types exist. ApiCompat covers the binary surface.
Usage in dotnet/runtime
No adoption sites exist beyond the target library itself — these are foundational built-in converters registered by System.Text.Json's default resolvers, not APIs consumed by other runtime code. The prototype wires them into the reflection resolver (DefaultJsonTypeInfoResolver), the source generator (KnownTypeSymbols + JsonSourceGenerator.Parser), and adds reflection + source-gen round-trip tests.
Background and motivation
System.Text.Jsonships built-in number converters for every primitive floating-point type plusHalf(added in #87994). The remaining built-in floating-point types —System.Numerics.BFloat16and the IEEE 754 decimal typesDecimal32/Decimal64/Decimal128(#81376) — have no built-in converter. They implementIFloatingPoint<T>exactly likefloat/double/Half, but today they cannot be (de)serialized as JSON numbers and require a hand-writtenJsonConverter<T>per type.Source-generated contexts need a public
JsonMetadataServicesproperty per built-in type to emit (JsonMetadataServices.HalfConverter, etc.); there is no such property for these four, so both the reflection and source-gen resolvers fall through to unsupported-type handling.This proposal adds the four missing properties, completing the built-in floating-point coverage.
NFloatis intentionally excluded: it is a platform-dependent alias offloat/double, so its JSON representation would vary by platform.Related: #87994 (Half), #81376 (Decimal32/64/128).
API Proposal
The properties are gated to the target framework where these types are available (
$(NetCoreAppCurrent)), matching the existing#if-guarded built-in converter properties.API Usage
Named literals and string number handling behave identically to the other floating-point converters:
Alternative Designs
HalfConverter. Rejected in the prototype in favor of a single internal generic converter constrained toIFloatingPointIeee754<T>(the interface exposing theNaN/Infinitymembers the converter needs) — all four types share the same parse/format/named-literal logic, so four near-identical files would be pure duplication. This is an implementation detail; the public surface is the four properties above either way.NFloat. Rejected:NFloatis a platform-dependent alias, so serializing it as a JSON number produces platform-dependent output.Risks
Adds four entries to the built-in simple-converter set, a small code-size/metadata increase for reflection and trimming scenarios on the target TFM. No binary or source breaking changes — these are pure additions gated behind the TFM where the underlying types exist.
ApiCompatcovers the binary surface.Usage in dotnet/runtime
No adoption sites exist beyond the target library itself — these are foundational built-in converters registered by
System.Text.Json's default resolvers, not APIs consumed by other runtime code. The prototype wires them into the reflection resolver (DefaultJsonTypeInfoResolver), the source generator (KnownTypeSymbols+JsonSourceGenerator.Parser), and adds reflection + source-gen round-trip tests.Note
This proposal was drafted with GitHub Copilot.