dotnet-sdk
dotnet-sdk copied to clipboard
Losing Precision of double value over 6 decimal places when PublishEventAsync is called
Expected Behavior
Publishing a model containing double values via PublishEventAsync shouldn't lose any precision.
Actual Behavior
We are dealing with some lat/longs in our codebase as doubles. They are sometimes accurate to 9 decimal places. The model containing these properties gets sent via PublishEventAsync, but when they hit the handler the double values are always getting rounded to 6 decimal places.
Steps to Reproduce the Problem
Example Call
public class DeliveryRequest
{
public double DeliveryLocationLatitude { get; set; }
public double DeliveryLocationLongitude { get; set; }
}
var model = new DeliveryRequest
{
DeliveryLocationLatitude = 53.7886918m
DeliveryLocationLongitude = -2.2299881m
}
await _daprClient.DaprClient.PublishEventAsync("pubsub", "UpdateDeliveryEvent", new UpdateDeliveryEvent(model), cancellationToken);
On the handler side when the model hit, the DeliveryLocationLatitude and DeliveryLocationLongitude properties have both been rounded to 6 decimal places, so they now look like
DeliveryLocationLatitude = 53.788692m
DeliveryLocationLongitude = -2.229988m
We have managed to get around this by creating a custom json converter to use on those 2 fields in the model, which writes the value out like so
public override void Write(Utf8JsonWriter writer, double value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString("G17", CultureInfo.InvariantCulture));
}
While this does work, its not ideal and probably should not be required?
@beakersoft - Is the ask here to allow full precision by default? If I had to guess, the default encoding truncates it to make it a more consistent parsing experience on the read side.
Instead of creating a customer parser, have you considered saving it as a string in your message? That'd guarantee the raw value and leave all the encoding/decoding responsibility to your code which gives you more control.
@beakersoft - this might be a silly question but just in case:
public class DeliveryRequest
{
public double DeliveryLocationLatitude { get; set; }
public double DeliveryLocationLongitude { get; set; }
}
var model = new DeliveryRequest
{
DeliveryLocationLatitude = 53.7886918m
DeliveryLocationLongitude = -2.2299881m
}
Your DeliveryRequest type is defining these properties with double but your initialization of the properties is using decimal (-2.2299881m) literals. Did you mean to define the properties as decimals?
Also as-of .NET 5 there is an attribute you can use to get string-serialization without writing a converter https://docs.microsoft.com/en-us/dotnet/api/system.text.json.serialization.jsonnumberhandlingattribute?view=net-6.0
@beakersoft - Are you still having problems here?
@halspang we've got around it by using the custom json converter, although it does feel a bit of a hack. We did think about just using a string, but again then feels a bit nasty as we would have to keep converting to/from the correct type
@beakersoft - Since you've found a way to handle this, I'm going to close this issue. If you think this is worth a feature add, please feel free to reopen this issue or create a more specific one with the requested behavior.