2017-01-30 20 views
4

でオブジェクトをデシリアライズするとき、私は、次のテストコードがあります。JsonConvert.DeserializeObjectへの呼び出しが2つのエラーを生成予期しないトークンJsonConvert.DeserializeObject

[TestClass] 
public class TestJsonDeserialize 
{ 
    public class MyClass 
    { 
     [JsonProperty("myint")] 
     public int MyInt { get; set; } 
     [JsonProperty("Mybool")] 
     public bool Mybool { get; set; } 
    } 

    [TestMethod] 
    public void Test1() 
    { 
     var errors = new List<string>(); 
     var json1 = "{\"myint\":1554860000,\"Mybool\":false}"; 
     var json2 = "{\"myint\":3554860000,\"Mybool\":false}"; 
     var i = JsonConvert.DeserializeObject<MyClass>(json2, new JsonSerializerSettings 
     { 
      Error = delegate (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args) 
      { 
       Debug.WriteLine(args.ErrorContext.Error.Message); 
       errors.Add(args.ErrorContext.Error.Message); 
       args.ErrorContext.Handled = true; 
      } 
     }); 
     Assert.IsTrue(errors.Count <= 1); 
    } 
} 

を。そのうちの1つは期待されているが、もう1つは期待されていない。 エラーは次のとおりです。

  • JSON整数3554860000がInt32では大きすぎるか小さすぎます。パス 'myint'、行1、位置19。
  • オブジェクトの逆シリアル化時に予期しないトークンがあります。パス 'Mybool'、1行目、34行目。

1番目のエラーは処理済みとマークされていますが、なぜ2番目のエラーがありますか? 私はすでにNewtonsoft.Json 8.0.2から9.0.1に更新しましたが、残っています。 最初の文字列(json2ではなくjson1)を渡すと、エラーはまったく発生しません。

答えて

4

更新

Issue 1194: JsonTextReader.ParseNumber leads to error after ThrowReaderErrorとして報告され、その後Json.NET 10.0.1としてリリースされた当時の現在のビルドでは再現できないようNewtonsoftによって閉じ。

オリジナル回答

これはJsonTextReaderのバグかもしれません。 JsonTextReader.ParseNumber(ReadType readType, char firstChar, int initialPosition)

幾分簡略化し、次のロジックがある:

else if (readType == ReadType.ReadAsInt32) 
{ 

// Snip 

     int value; 
     ParseResult parseResult = ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value); 
     if (parseResult == ParseResult.Success) 
     { 
      numberValue = value; 
     } 
     else if (parseResult == ParseResult.Overflow) 
     { 
      throw ThrowReaderError("JSON integer {0} is too large or small for an Int32.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); 
     } 
     else 
     { 
      throw ThrowReaderError("Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); 
     } 
    } 

    numberType = JsonToken.Integer; 
} 

// Snip 
// Finally, after successfully parsing the number 

ClearRecentString(); 

// index has already been updated 
SetToken(numberType, numberValue, false); 

は例外がThrowReadError()によってスローされた時点で、ストリームの位置があまりにも大きい整数を越えて進められています。ただし、JsonReader.TokenTypeの値は更新されておらず、正常に解析された最後のトークン、つまり"myint"の名前に対しても、JsonToken.PropertyNameが返されます。その後、例外が呑み込まれて無視された後、ストリームの位置と現在のトークンの値の不一致により"Mybool"プロパティ名がスキップされ、2番目のエラーが発生します。

デバッガでは、例外がスローされたとき、私は手動で

SetToken(JsonToken.Undefined); 
ClearRecentString(); 

を呼び出す次に、ファイルの残りの部分は正常に解析することができ、場合。 (ここではJsonToken.Undefinedが正しい選択であるとは確信していません)

ニュートンソフトにはreport an issueが必要です。

JsonReaderがエラーハンドラに渡されていないので、私は見つけることができる唯一の回避策は、次のようにJsonTextReaderをサブクラス化することです。

public class FixedJsonTextReader : JsonTextReader 
{ 
    public FixedJsonTextReader(TextReader reader) : base(reader) { } 

    public override int? ReadAsInt32() 
    { 
     try 
     { 
      return base.ReadAsInt32(); 
     } 
     catch (JsonReaderException) 
     { 
      if (TokenType == JsonToken.PropertyName) 
       SetToken(JsonToken.None); 
      throw; 
     } 
    } 
} 

そして実行します。

var errors = new List<string>(); 
var json2 = "{\"myint\":3554860000,\"Mybool\":false}"; 

using (var reader = new FixedJsonTextReader(new StringReader(json2))) 
{ 
    var settings = new JsonSerializerSettings 
    { 
     Error = delegate(object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args) 
     { 
      Debug.WriteLine(args.ErrorContext.Error.Message); 
      errors.Add(args.ErrorContext.Error.Message); 
      args.ErrorContext.Handled = true; 
     } 
    }; 
    var i = JsonSerializer.CreateDefault(settings).Deserialize<MyClass>(reader); 
} 
Assert.IsTrue(errors.Count <= 1); // Passes 
+1

workouround私のテストプロジェクトのために働く。どうもありがとう。私はあなたが提案したようにギトップに関する問題を報告しました。 – huha

関連する問題