2016-01-07 17 views
5

Sau khi nâng cấp một cơ sở mã để sử dụng Json.NET 8.0.1, một số sterbles deserialization. Sử dụng Json.NET 7.0.1 mọi thứ hoạt động tốt. Rõ ràng nó là deserialization của một tài sản của loại byte[] gây ra vấn đề. Nếu tôi loại bỏ các tài sản byte[] nó hoạt động tốt. Tôi có thể mô phỏng hành vi sử dụng giao diện điều khiển này ứng dụng đơn giản:Không thể deserialize một đối tượng với một thuộc tính mảng byte bằng cách sử dụng 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; } 
} 

File accounts.json trông như thế này:

{ 
    "$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" 
    } 
} 

Đây có phải là có thể là một lỗi trong Json.NET 8.0.1 hoặc tôi có thể có thể giải quyết việc này bằng cách tinh chỉnh JsonSerializerSettings?

Nếu có ai đang cố gắng tái tạo điều này, hãy đảm bảo đồng bộ tên lắp ráp trong tệp accounts.json với tên lắp ráp của ứng dụng bảng điều khiển (trong trường hợp này là ConsoleApplication1).

Trả lời

2

Cập nhật

Fixed trong sự thay đổi thiết lập 70120ce, mà sẽ được đưa vào Json.NET 8.0.2.

gốc trả lời

Xác nhận - điều này dường như là một hồi quy. Hãy xem xét các lớp thử nghiệm đơn giản sau đây:

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

Bây giờ nếu tôi cố gắng khứ hồi lớp với TypeNameHandling.Objects:

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"); 
    } 

tôi nhận được ngoại lệ sau đây:

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() 

Trường hợp ngoại lệ không không xảy ra trong Json 7.0. Bạn nên report an issue.

Trong khi đó, bạn có thể sử dụng bộ chuyển đổi sau đây để làm việc xung quanh vấn đề này:

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(); 
    } 
} 

Với thiết lập

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

mát, nhờ xác nhận và thực hiện giải pháp. Tôi đã báo cáo sự cố trên GitHub. –

Các vấn đề liên quan