Ich habe eine MVC-Anwendung und ich handle etwas JSON darin. Das ist einfach. Ich habe dieses einfache Stück Code in meinem ModelBinder:Umgang mit Dezimalwerten in Newtonsoft.Json
return JsonConvert.DeserializeObject(jsonString, bindingContext.ModelType, new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore,
Formatting = Formatting.None,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
FloatParseHandling = FloatParseHandling.Decimal
});
Und es funktioniert einwandfrei.
Nun, irgendwie.
Lassen Sie uns sagen, ich habe diese Klasse:
public class MyClass
{
public decimal MyProp { get; set; }
}
Wenn ich versuche, dieses json zu deserialisieren:
"{\"MyProp\": 9888.77}"
Natürlich funktioniert es, da 9888.77
ein Gleitkommawert Javascript ist. Ich denke.
Aber ich einen maskierten Eingang für Geld in meine Seite, die die JSON sieht wie folgt aus (sorry über mein Englisch) macht:
"{\"MyProp\": \"9.888,77\" }"
aaand, versagt es. Es sagt, dass es Could not convert string to decimal
ist.
Ok, das ist fair. Es ist kein JS-Float, aber Convert.ToDecimal("9.888,77")
funktioniert so, wie ich es möchte.
Ich habe einige Tutorials im Internet über benutzerdefinierte Deserializer gelesen, aber es ist für mich unantastbar, einen benutzerdefinierten Deserializer für jede einzelne Klasse zu definieren, die ich in meiner Anwendung habe.
Was ich will, ist einfach zu definieren, wie JSON.Net eine Zeichenfolge in eine Dezimal-Eigenschaft in jeder Klasse konvertiert, die ich jemals deserialize werden möchten. Ich möchte die Convert.ToDecimal
Funktion in den Prozess der Konvertierung von Dezimalzahlen injizieren, wenn der aktuelle Konverter nicht funktioniert.
Gibt es einen Weg, ich könnte es tun?
Ich dachte, es gibt einen Weg, es zu tun, also habe ich meinen Code ein wenig geändert.
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);
Und schuf diese Klasse:
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;
}
}
}
}
Aber es ist sehr hässlich: es führt, was ich will nur, wenn er abstürzt, und hängt von base.ReadAsDecimal()
abstürzt. Es könnte nicht hässlicher sein.
Und funktioniert nicht: Error converting value "1.231,23" to type 'System.Nullable1[System.Decimal]'. Path 'MyProp', line X, position Y.
Der Wert selbst umgewandelt wird, aber vielleicht aus irgendeinem Grunde versucht es noch die Zeichenfolge „1.231,23“ in eine Dezimalzahl zu setzen.
Also, gibt es eine Möglichkeit, es richtig zu machen?
Funktioniert wie ein Charme. Um eine sichere Rückkehr von Nullable-Dezimalzahlen zu gewährleisten, habe ich die folgenden Änderungen an einer der conditionals if (token.Type == JTokenType.String) { Dezimal d; if (Decimal.TryParse (token.ToString(), System.Globalization.NumberStyles.AllowParentheses, System.Globalization.CultureInfo.CurrentCulture, aus d)) return d; sonst Rückgabewert null; } – Arjmand