Edit: Nearly 5 years have passed and I don't think this is the way to go. The client must publish the data in the correct numerical format. With current environments such as React or Angular, or with the right architecture, handling, and error checking, I think this is almost no problem.
But if someone wants to tighten the muscles of Json.NET, feel free to check the answers.
I have an MVC application and I am processing some JSON in it. So simple. I have this simple piece of code in my ModelBinder:
return JsonConvert.DeserializeObject(jsonString, bindingContext.ModelType, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Ignore, Formatting = Formatting.None, DateFormatHandling = DateFormatHandling.IsoDateFormat, FloatParseHandling = FloatParseHandling.Decimal });
And it works flawlessly.
Well, sort of.
Let's say I have this class:
public class MyClass { public decimal MyProp { get; set; } }
If I try to deserialize this JSON:
"{\"MyProp\": 9888.77}"
Of course, this works, since 9888.77 is a Javascript floating point value. I think.
But on my page there is a disguised input of money that makes JSON like this (sorry for my English):
"{\"MyProp\": \"9.888,77\" }"
AAAND, this fails. He says that Could not convert string to decimal .
Well, thatβs fair. This is not a JS float, but Convert.ToDecimal("9.888,77") works the way I want.
I read some tutorials about custom deserializers on the Internet, but I cannot define my own deserializer for each class that is in my application.
I just want to override the way JSON.Net converts a string to a decimal property, in any class that I ever want to deserialize to. I want the Convert.ToDecimal function Convert.ToDecimal to process decimal fractions when the current converter is down.
Is there any way I could do this?
I thought there was a way to do this, so I changed my code a bit.
JsonSerializer serializer = new JsonSerializer { NullValueHandling = NullValueHandling.Ignore, MissingMemberHandling = MissingMemberHandling.Ignore, Formatting = Formatting.None, DateFormatHandling = DateFormatHandling.IsoDateFormat, FloatParseHandling = FloatParseHandling.Decimal, }; return serializer.Deserialize(new DecimalReader(jsonStr), bindingContext.ModelType);
And created this class:
public class DecimalReader : JsonTextReader { public DecimalReader(string s) : base(new StringReader(s)) { } public override decimal? ReadAsDecimal() { try { return base.ReadAsDecimal(); } catch (Exception) { if (this.TokenType == JsonToken.String) { decimal value = 0; bool convertible = Decimal.TryParse(this.Value.ToString(), out value); if (convertible) { return new Nullable<decimal>(value); } else { throw; } } else { throw; } } } }
But this is very ugly: it does what I want only when it crashes, and depends on base.ReadAsDecimal() . It could not have been more ugly.
And it does not work : Error converting value "1.231,23" to type 'System.Nullable1[System.Decimal]'. Path 'MyProp', line X, position Y. Error converting value "1.231,23" to type 'System.Nullable1[System.Decimal]'. Path 'MyProp', line X, position Y. Error converting value "1.231,23" to type 'System.Nullable1[System.Decimal]'. Path 'MyProp', line X, position Y. Error converting value "1.231,23" to type 'System.Nullable1[System.Decimal]'. Path 'MyProp', line X, position Y.
The value itself is converted, but perhaps for some reason it is still trying to put the string "1.231.23" in decimal.
So, is there a way to do this right?