Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom Converter fails when both decimal and doubles are present #2941

Open
steffenskov opened this issue Mar 15, 2024 · 3 comments
Open

Custom Converter fails when both decimal and doubles are present #2941

steffenskov opened this issue Mar 15, 2024 · 3 comments

Comments

@steffenskov
Copy link

Source/destination types

internal record Example(double Double, decimal Decimal);

Source/destination JSON

{"Double":-1.7976931348623157E+308,"Decimal":-79228162514264337593543950335.0}

Expected behavior

I expect to be able to deserialize the JSON back into an Example record, even when using this custom JsonConverter:

class CustomConverter : JsonConverter
{
	public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
	{
		// Not relevant
	}

	public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
	{
		var token = JToken.ReadFrom(reader);
		var dbl = double.Parse(token["Double"]!.ToString());
		var dec = decimal.Parse(token["Decimal"]!.ToString()); // Throws FormatException
		return new Example(dbl, dec);
	}

	public override bool CanConvert(Type objectType) => true;
}

Actual behavior

A FormatException is thrown when attempting to parse the decimal, because the reader by default treats all floating point numbers the same via the FloatParseHandling property. Changing the FloatParseHandling property to Decimal just moves the problem to parsing the double instead.

Steps to reproduce

var example = new Example(double.MinValue, decimal.MinValue);
var json = JsonConvert.SerializeObject(example);
var deserialized = JsonConvert.DeserializeObject<Example>(json, new CustomConverter());
@steffenskov
Copy link
Author

This seems related: #2839

@steffenskov
Copy link
Author

I've narrowed it down to line 2204 in JsonTextReader.cs, where it inspects _floatParseHandling. Wouldn't a fallback mechanism here work?
e.g. attempting conversion to decimal, and if it overflows go to double instead of throwing?
I realize it should probably have a new FloatParseHandling enum value to avoid breaking existing implementations. Something like DecimalWithFallbackToDouble (or something more concise)

Just an idea.

@mtrackeros
Copy link

Typy źródłowe/docelowe

internal record Example(double Double, decimal Decimal);

Źródłowy/docelowy kod JSON

{"Double":-1.7976931348623157E+308,"Decimal":-79228162514264337593543950335.0}

Oczekiwane zachowanie

Oczekuję, że będzie można deserializować kod JSON z powrotem do przykładowego rekordu, nawet w przypadku korzystania z tego niestandardowego:JsonConverter

class CustomConverter : JsonConverter
{
	public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
	{
		// Not relevant
	}

	public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
	{
		var token = JToken.ReadFrom(reader);
		var dbl = double.Parse(token["Double"]!.ToString());
		var dec = decimal.Parse(token["Decimal"]!.ToString()); // Throws FormatException
		return new Example(dbl, dec);
	}

	public override bool CanConvert(Type objectType) => true;
}

Rzeczywiste zachowanie

A jest zgłaszany podczas próby przeanalizowania ułamka dziesiętnego, ponieważ czytelnik domyślnie traktuje wszystkie liczby zmiennoprzecinkowe tak samo za pośrednictwem właściwości. Zmiana właściwości na po prostu przenosi problem do analizowania zamiast tego.FormatException``FloatParseHandling``FloatParseHandling``Decimal``double

Steps to reproduce

var example = new Example(double.MinValue, decimal.MinValue);
var json = JsonConvert.SerializeObject(example);
var deserialized = JsonConvert.DeserializeObject<Example>(json, new CustomConverter());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants