2016-08-10 3 views
6

精度を維持するために、長い小数の値を含むJSONをカスタムタイプに逆シリアル化したい(つまり、カスタムBigDecimalクラス)。私はJson.NET 9.0.1と.NET 4.6.1を使用しています。私はJsonConverterを使用しようとしましたが、ReadJsonが呼び出されたときに使用可能な値はすでに.NETのdecimal型としてJson.NETによって識別され、読み取られており、その精度に限定されているようです。Json.NETで高精度10進値を逆シリアル化するにはどうすればよいですか?

理想的には、生の文字列にアクセスしてカスタムタイプに入れることができます。私はターゲットオブジェクトの文字列プロパティを使用することができますし、完全な文字列を逆シリアル化しますが、私はオブジェクトをさらに処理しなければならない(つまり、別の表現にコピーする)と、特に大規模なスキーマで乱雑です。

もっと良いアプローチをお考えですか?ここで


は、ターゲットクラスです:

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

は番目の場合は、試みることができますあなたが期待するとして、電子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 assertはすでに引用符で修飾せずに私のために動作します。私も失敗したあなたのdotnetfiddleの例に合わせて.NET 4.5 /コンソールバージョンを試しました。違いが何であるか分かりません。 – jlalughery

関連する問題