JObject.Parse修改浮点值的结束

时间:2014-10-21 10:11:22

标签: json.net

var clientString = "{\"max\":1214.704958677686}";

JObject o = JObject.Parse(clientString);

var jsonString = o.ToString();

jsonString的内容:

{
  "max": 1214.7049586776859
}

这是在可视化对象和执行ToString()时。请注意,686神秘地扩展到6859(精度添加)。这对我们来说是一个问题,因为数字不完全相同,以后json上的哈希函数不匹配。

3 个答案:

答案 0 :(得分:5)

您的值更改的原因是由于.NET中浮点数的性质。 JObject.Parse(clientString)方法在某个时刻执行以下行:

double d;
double.TryParse("1214.704958677686", NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out d);

其中d表示您在JObject中获得的数字。

由于d的类型为double,double是浮点数,因此您没有得到预期的值。详细了解Binary floating point and .NET

JSON.NET中有一个选项可以将浮点数解析为小数并获得所需的精度,但要做到这一点,您需要创建与json字符串匹配的自定义类并反序列化json。像这样:

public class MyClass
{
    [JsonProperty("max")]
    public decimal Max { get; set; }
}


var obj = JsonConvert.DeserializeObject<MyClass>(clientString, new JsonSerializerSettings
          {
              FloatParseHandling = FloatParseHandling.Decimal
          });

通过使用此代码示例,max属性的值不会更改。

答案 1 :(得分:3)

@Ilija Dimov是正确的 - 默认情况下,JSON.NET将JSON浮动解析为double。如果您仍想使用JObject而不是创建完整的POCO以进行反序列化,则可以使用JsonTextReader并设置FloatParseHandling选项:

var reader = new JsonTextReader(new StringReader(clientString));
reader.FloatParseHandling = FloatParseHandling.Decimal;

JObject obj = JObject.Load(reader);

Console.WriteLine(obj["max"].Value<decimal>()); // 1214.704958677686

答案 2 :(得分:1)

您可以通过解析为float,double和decimal来尝试此行为:

Assert.AreEqual(1214.705f,float.Parse("1214.704958677686"));
Assert.AreEqual(1214.7049586776859, double.Parse("1214.704958677686"));
Assert.AreEqual(1214.704958677686, decimal.Parse("1214.704958677686"));

所以json.net使用double作为中间类型。您可以通过设置FloatParseHandling option来更改此设置。