2016-08-10 37 views
6

我想將包含長十進制值的JSON反序列化爲自定義類型以保持其精度(即自定義BigDecimal類)。我使用的是Json.NET 9.0.1和.NET 4.6.1。我試過使用JsonConverter,但似乎調用ReadJson時可用的值已被Json.NET識別並讀取爲.NET十進制類型,並且僅限於其精度。如何使用Json.NET反序列化高精度十進制值?

理想情況下,我將有權訪問原始字符串,以便我可以將其放入自定義類型中。我可以在目標對象上使用字符串屬性,並對整個字符串進行反序列化,但是我必須進一步處理對象(即將其複製到另一個表示中),這在大型模式中尤其麻煩。

有關更好方法的任何想法?


這裏的目標類:

public class DecimalTest 
{ 
    public string stringValue { get; set; } 
    public decimal decimalValue { get; set; } 
    public BigDecimal bigDecimalValue { get; set; } 
} 

下面是使用JSON測試:

[TestMethod] 
    public void ReadBigDecimal_Test() 
    { 
     var json = @"{ 
      ""stringValue"" : 0.0050000012852251529693603515625, 
      ""decimalValue"" : 0.0050000012852251529693603515625, 
      ""bigDecimalValue"" : 0.0050000012852251529693603515625 
     }"; 

     var settings = new JsonSerializerSettings(); 
     settings.FloatParseHandling = FloatParseHandling.Decimal; 
     settings.Converters.Add(new JsonBigDecimalConverter()); 

     var result = JsonConvert.DeserializeObject<DecimalTest>(json, settings); 

     Assert.IsNotNull(result); 
     Assert.AreEqual("0.0050000012852251529693603515625", result.stringValue); 
     Assert.AreEqual(0.0050000012852251529693603516m, result.decimalValue); 

     // *** This case fails *** 
     Assert.AreEqual("0.0050000012852251529693603515625", result.bigDecimalValue.ToString()); 
    } 

這裏的定製轉換器:

public class JsonBigDecimalConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return (objectType == typeof(BigDecimal)); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     // *** reader.Value here already appears to be a .NET decimal. 
     // *** If I had access to the raw string I could get this to work. 
     return BigDecimal.Parse(reader.Value.ToString()); 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 
     throw new NotImplementedException(); 
    } 
} 

回答

1

你能嘗試,如果日E採用實施ReadJson作品如您所願:

public override object ReadJson(
    JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
{ 
    var token = JToken.Load(reader); 
    return BigDecimal.Parse(token.ToString()); 
} 

更新

不幸的是,上面將無法工作。似乎沒有辦法從JSON數據中讀取原始字符串。

另請注意,在我的測試中,斷言stringValue首先失敗。看到這個工作示例:https://dotnetfiddle.net/s0pqg3

我認爲這是因爲Json.NET內部根據指定的FloatParseHandling立即解析它遇到的任何number令牌。原始數據從未被保存。

我認爲唯一的解決辦法是換大十進制字符串引號,像這樣:

"bigDecimalValue" : "0.0050000012852251529693603515625" 

這裏是一個工作的例子,正是這麼做的,爲了保持期望精度:https://dotnetfiddle.net/U1UG3z

+0

謝謝看着它。出於某種原因,stringValue聲明已經適用於我,但沒有用引號限定它。我也試過.NET 4.5/console版本來匹配你的dotnetfiddle例子失敗;不知道有什麼區別。 – jlalughery