2016-01-07 9 views
5

Json.NET 8.0.1を使用するようにコードベースをアップグレードした後、一部の逆シリアル化が失敗します。 Json.NET 7.0.1を使用するとすべて正常に動作します。明らかに、この問題の原因となるタイプbyte[]のプロパティを逆シリアル化しています。 byte[]プロパティを削除してもうまく動作します。Json.NET 8.0.1を使用してバイト配列プロパティを持つオブジェクトを逆シリアル化できません

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     Dictionary<string, Account> accounts; 
     var jsonSerializerSettings = new JsonSerializerSettings 
     { 
      TypeNameHandling = TypeNameHandling.Objects, 
      TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple 
     }; 

     using (var streamReader = new StreamReader("accounts.json")) 
     { 
      var json = streamReader.ReadToEnd(); 
      accounts = JsonConvert.DeserializeObject<Dictionary<string, Account>>(json, jsonSerializerSettings); 
     } 

     foreach (var account in accounts) 
     { 
      Debug.WriteLine(account.Value.Name); 
     } 
    } 
} 

internal class Account 
{ 
    public string Id { get; set; } 

    public string Name { get; set; } 

    public byte[] EncryptedPassword { get; set; } 
} 

accounts.jsonファイルは次のようになります:

{ 
    "$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[ConsoleApplication1.Account, ConsoleApplication1]], mscorlib", 
    "lars.michael": { 
     "$type": "ConsoleApplication1.Account, ConsoleApplication1", 
     "EncryptedPassword": { 
      "$type": "System.Byte[], mscorlib", 
      "$value": "cGFzc3dvcmQ=" 
     }, 
     "Name": "Lars Michael", 
     "Id": "lars.michael" 
    }, 
    "john.doe": { 
     "$type": "ConsoleApplication1.Account, ConsoleApplication1", 
     "EncryptedPassword": { 
      "$type": "System.Byte[], mscorlib", 
      "$value": "cGFzc3dvcmQ=" 
     }, 
     "Name": "John Doe", 
     "Id": "john.doe" 
    } 
} 

はJson.NET 8.0.1でこの多分バグですか、私は多分これを解決することができ、私はこの単純なコンソールアプリケーションを使用して動作を再現することができますJsonSerializerSettingsを調整することで?

誰でもこれを再生しようとしている場合は、accounts.jsonファイルのアセンブリ名をコンソールアプリケーションのアセンブリ名(この場合はConsoleApplication1)と同期させてください。変化

答えて

2

更新

Fixed Json.NET 8.0.2に含まれる70120ceを設定します。

オリジナル回答

を確認 - これが回帰ように見えます。例外はありません

Newtonsoft.Json.JsonSerializationException: Additional text found in JSON string after finishing deserializing object. 
    at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 196 
    at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\JsonSerializer.cs:line 823 
    at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\JsonSerializer.cs:line 802 
    at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\JsonConvert.cs:line 863 
    at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\JsonConvert.cs:line 820 
    at Question34654184.TestClass.TestRoundTrip[T](T item, JsonSerializerSettings jsonSerializerSettings) 
    at Question34654184.TestClass.TestRoundTrip[T](T item) 
    at Question34654184.TestClass.TestSimple() 

:私は、次の例外を取得

private static void TestSimple() 
    { 
     var test = new HasByteArray { EncryptedPassword = Convert.FromBase64String("cGFzc3dvcmQ=") }; 
     try 
     { 
      TestRoundTrip(test); 
     } 
     catch (Exception ex) 
     { 
      Debug.WriteLine(ex); 
     } 
    } 

    private static void TestRoundTrip<T>(T item) 
    { 
     var jsonSerializerSettings = new JsonSerializerSettings 
     { 
      TypeNameHandling = TypeNameHandling.Objects, 
      TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple 
     }; 

     TestRoundTrip<T>(item, jsonSerializerSettings); 
    } 

    private static void TestRoundTrip<T>(T item, JsonSerializerSettings jsonSerializerSettings) 
    { 
     var json = JsonConvert.SerializeObject(item, Formatting.Indented, jsonSerializerSettings); 
     Debug.WriteLine(json); 

     var item2 = JsonConvert.DeserializeObject<T>(json, jsonSerializerSettings); 

     var json2 = JsonConvert.SerializeObject(item2, Formatting.Indented, jsonSerializerSettings); 

     Debug.WriteLine(json2); 

     if (!JToken.DeepEquals(JToken.Parse(json), JToken.Parse(json2))) 
      throw new InvalidOperationException("Round Trip Failed"); 
    } 

を:私はTypeNameHandling.Objectsを持つクラスを往復しようとすると今

internal class HasByteArray 
{ 
    public byte[] EncryptedPassword { get; set; } 
} 

:以下の簡単なテストクラスを考えてみましょうJson 7.0では発生しません。あなたはreport an issueです。一方

、あなたは問題を回避するには、以下のコンバータを使用することができます。

public class ByteArrayConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return objectType == typeof(byte[]); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.Null) 
      return null; 
     var token = JToken.Load(reader); 
     if (token == null) 
      return null; 
     switch (token.Type) 
     { 
      case JTokenType.Null: 
       return null; 
      case JTokenType.String: 
       return Convert.FromBase64String((string)token); 
      case JTokenType.Object: 
       { 
        var value = (string)token["$value"]; 
        return value == null ? null : Convert.FromBase64String(value); 
       } 
      default: 
       throw new JsonSerializationException("Unknown byte array format"); 
     } 
    } 

    public override bool CanWrite { get { return false; } } // Use the default implementation for serialization, which is not broken. 

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

設定

  var jsonSerializerSettings = new JsonSerializerSettings 
      { 
       TypeNameHandling = TypeNameHandling.Objects, 
       TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple, 
       Converters = new [] { new ByteArrayConverter() }, 
      }; 
+1

クール、確認と回避策については感謝して。私はGitHubの問題を報告しました。 –

関連する問題