FloatParseHandling
specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. (It is not applicable during writing or serialization, when Json.NET should write both decimal
and double
values with as much precision as necessary.) There is no built-in attribute to temporarily toggle JsonReader.FloatParseHandling
during deserialization of a specific property. When deserializing a statically typed property such as
List<decimal> values { get; set; }
this is not an issue because the serializer tells the reader the required floating-point type. Only when deserializing to a dynamic
property does this become problematic.
Thus what you can do is to create a custom JsonConverter
that temporarily resets the value of JsonReader.FloatParseHandling
, then allocates and populates the object being deserialized, like so:
public class FloatParseHandlingConverter : JsonConverter
{
readonly FloatParseHandling floatParseHandling;
public FloatParseHandlingConverter(FloatParseHandling floatParseHandling)
{
this.floatParseHandling = floatParseHandling;
}
public override bool CanConvert(Type objectType)
{
throw new NotImplementedException();
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
var old = reader.FloatParseHandling;
try
{
reader.FloatParseHandling = floatParseHandling;
existingValue = existingValue ?? serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
serializer.Populate(reader, existingValue);
return existingValue;
}
finally
{
reader.FloatParseHandling = old;
}
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then apply it to your rows
property as follows:
class TestData
{
[JsonConverter(typeof(FloatParseHandlingConverter), FloatParseHandling.Decimal)]
public List<Row> rows;
}
Sample working .Net fiddle.
As an aside, note that, if you have a dynamic property that might have a decimal value, like so:
public class Parent
{
dynamic value { get; set; }
}
then applying the converter directly to the property will not work. This is because, at the time JsonConverter.ReadJson()
is called, the reader has already advanced to the value string and tokenized it as a double
. Thus the converter must be applied to a container type or property, e.g.:
[JsonConverter(typeof(FloatParseHandlingConverter), FloatParseHandling.Decimal)]
public class Parent
{
// [JsonConverter(typeof(FloatParseHandlingConverter), FloatParseHandling.Decimal)] will not work
dynamic value { get; set; }
}
This dovetails with the specific case of this question since you want the deserialized floating-point values inside Row
to be interpreted as decimal
only within TestData
.