dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.91k stars 4.63k forks source link

[API Proposal]: Utf8JsonWriter.WriteNumberValue<TNumber> #103905

Open dellamonica opened 2 months ago

dellamonica commented 2 months ago

Background and motivation

Use the new generic number types in the JSON API. Motivation: we can write higher level methods on top of the JsonWriter, for instance, to write an array of numeric values without having to repeat the same code block for each numeric type.

API Proposal


public void WriteNumberValue<TNumber>(TNumber number) where TNumber: INumber<TNumber>

API Usage


public void WriteArray(Utf8JsonWriter jw, ReadOnlySpan<TNumber> values) where TNumber: INumber<TNumber>
{     
        jw.WriteStartArray();
        foreach (TNumber val in values)
        {
            jw.WriteNumberValue(val);
        }
        jw.WriteEndArray();
}

...

WriteArray(jw, [3.14f, 2.71f, 0f]);
WriteArray(jw, [1, 2, 3]);

Alternative Designs

No response

Risks

No response

dotnet-policy-service[bot] commented 2 months ago

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis See info in area-owners.md if you want to be subscribed.

eiriktsarpalis commented 2 months ago

We'd probably also need a Utf8JsonReader.ReadNumber<T>() where TNumber: INumber<TNumber> as well. Sounds doable, INumber implements both IUtf8SpanFormattable and IUtf8SpanParsable.

cc @tannergooding

Clockwork-Muse commented 2 months ago

.... Some recommendations around currency and JSON often say that such numbers should be serialized as string values, not as "raw" JSON numbers (which can silently end up as binary floating point in some circumstances). Given decimal implements INumber, that might have some adverse effects.

elgonzo commented 2 months ago

such numbers should be serialized as string values, not as "raw" JSON numbers (which can silently end up as binary floating point in some circumstances)

Writing numbers as string values is not the concern of the existing Utf8JsonWriter.WriteNumber and WriteNumberValue methods, it would be inconsistent and confusing when WriteNumberValue\<TNumber> happens to write a json string and not a json number (not to mention that a method name like "WriteNumberValue" would then be a rather misleading name for a method that doesn't write a number value). If you need to workaround poor json reader/deserialization routines or target environments lacking decimal number types other than binary floating points, a custom json converter that writes decimals as json strings is in my opinion a more appropriate choice to address this issue.

Given decimal implements INumber, that might have some adverse effects.

Considering that there are already WriteNumber/WriteNumberValue methods for decimals which write them as json numbers, I fail to see how a generic WriteNumberValue\<TNumber> method writing decimals as a json number would introduce any adverse effects.