2015-05-21 12 views
5
JObject j = JObject.Parse("{'responseArray':'AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA'}"); 

    byte[] r = j["responseArray"].ToObject<byte[]>(JsonSerializer.Create(new JsonSerializerSettings())); 

Output dự kiến ​​(chỉ hoạt động tốt với JSON.net v4.5.6.14930)base64 deserializing mã hóa mảng byte trả lại kết quả khác nhau trong 2 JSON.net phiên bản thư viện

r = {byte[24]} 
     [0]: 0 
     [1]: 0 
     [2]: 0 
     [3]: 0 
     [4]: 0 
     [5]: 0 
     [6]: 0 
     [7]: 0 
     [8]: 0 
     [9]: 0 
     [10]: 0 
     [11]: 0 
     [12]: 0 
     [13]: 0 
     [14]: 0 
     [15]: 0 
     [16]: 0 
     [17]: 0 
     [18]: 0 
     [19]: 0 
     [20]: 1 
     [21]: 0 
     [22]: 0 
     [23]: 0 

deserializing mã trên trong JSON. v6.0.8.18111 ròng cho kết quả errorneous

Output sai (JSON.net v6.0.8.18111)

r= {byte[16]} 
    [0]: 170 
    [1]: 170 
    [2]: 170 
    [3]: 170 
    [4]: 170 
    [5]: 170 
    [6]: 170 
    [7]: 170 
    [8]: 170 
    [9]: 170 
    [10]: 170 
    [11]: 170 
    [12]: 170 
    [13]: 171 
    [14]: 170 
    [15]: 170 

Tôi có làm gì sai ở đây không?

Lưu ý- Đoạn mã trong câu hỏi là một phần của một đoạn mã phức tạp, trong đó dữ liệu được đưa vào như tham số JSON cho WebMethod, responsearray là một phần của đối tượng phức tạp được gửi vào webmethod. sử dụng thư viện JSON.net để giải mã.

+0

Sẽ hữu ích nếu bạn cung cấp chi tiết cụ thể. Ví dụ. "... cho kết quả sai ..." - kết quả là gì, tại sao nó sai. Hoặc, "... lấy sai lầm này ..." - "cái này" ở đây là gì? –

+0

đã chỉnh sửa câu hỏi cụ thể hơn –

Trả lời

0

Vấn đề là JObject đã phân tích các AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA như một string (j["responseArray"].Type == JTokenType.String), do đó j["responseArray"].ToObject<byte[]> không được làm một de-base64.

Bạn cần phải phân tích nó trực tiếp đến một byte[], như:

public class MyObject 
{ 
    public byte[] responseArray { get; set; } 
} 

MyObject cl = JsonConvert.DeserializeObject<MyObject>("{'responseArray':'AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA'}"); 

Rõ ràng bạn có thể làm Convert.FromBase64String "bằng tay":

JObject j = JObject.Parse("{'responseArray':'AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA'}"); 
byte[] r = Convert.FromBase64String((string)j["responseArray"]); 
+0

tôi đã chỉnh sửa câu hỏi cụ thể hơn. Tôi nghĩ rằng Convert.FromBase64String ((string) j ["responseArray"]); không phù hợp với yêu cầu của chúng tôi ở đây. –

+0

@RuhaimIzmeth Nếu bạn có thể thực hiện 'j [" responseArray "]' thì bạn có thể thực hiện một 'Convert.FromBase64String ((chuỗi) j [" responseArray "])'. Không có cách nào đơn giản chỉ sử dụng 'JObject.Parse' để trực tiếp deserialize một' byte [] ' – xanatos

+0

Nhưng nó hoạt động tốt với JSON.net v4.5.6.14930 –

6

Cập nhật

Đây là fixed trong Json.NET 7.0 Release 1.

gốc trả lời

Đây là một vấn đề Json.NET. Vấn đề là chuỗi của bạn AAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA chỉ xảy ra là thành công được phân tách như một GUID, trong JsonReader.ReadAsBytesInternal():

  if (s.Length == 0) 
      { 
       data = new byte[0]; 
      } 
      else if (ConvertUtils.TryConvertGuid(s, out g)) 
      { 
       data = g.ToByteArray(); 
      } 
      else 
      { 
       data = Convert.FromBase64String(s); 
      } 

Tại traceback này:

Newtonsoft.Json.JsonReader.ReadAsBytesInternal() Line 517 C# 
Newtonsoft.Json.Linq.JTokenReader.ReadAsBytes() Line 74 + 0x9 bytes C# 
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(Newtonsoft.Json.JsonReader reader = {Newtonsoft.Json.Linq.JTokenReader}, Newtonsoft.Json.Serialization.JsonContract contract = {Newtonsoft.Json.Serialization.JsonPrimitiveContract}, bool hasConverter = false) Line 1853 + 0x8 bytes C# 
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(Newtonsoft.Json.JsonReader reader = {Newtonsoft.Json.Linq.JTokenReader}, System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}, bool checkAdditionalContent = false) Line 144 + 0x2f bytes C# 
Newtonsoft.Json.JsonSerializer.DeserializeInternal(Newtonsoft.Json.JsonReader reader = {Newtonsoft.Json.Linq.JTokenReader}, System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}) Line 710 + 0x52 bytes C# 
Newtonsoft.Json.JsonSerializer.Deserialize(Newtonsoft.Json.JsonReader reader = {Newtonsoft.Json.Linq.JTokenReader}, System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}) Line 689 + 0x11 bytes C# 
Newtonsoft.Json.Linq.JToken.ToObject(System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}, Newtonsoft.Json.JsonSerializer jsonSerializer = {Newtonsoft.Json.JsonSerializer}) Line 1837 + 0x11 bytes C# 
Newtonsoft.Json.Linq.JToken.ToObject(System.Type objectType = {Name = "Byte[]" FullName = "System.Byte[]"}) Line 1811 + 0x3c bytes C# 
Newtonsoft.Json.Linq.JToken.ToObject<byte[]>() Line 1698 + 0x39 bytes C# 

Như bạn có thể thấy, đây ngắn mạch cơ sở 64 giải mã. Lỗi xấu xí, và thay vào đó là may mắn về phía bạn để có được chuỗi chính xác đó.

Để chặn nhận dạng GUID không phù hợp của Json.NET, bạn có thể tạo toàn bộ JsonConverter toàn cầu của mình cho mảng byte. Khi bạn làm thế, Json.NET sẽ vượt qua cho bạn những chuỗi nguyên mà không có sự "hữu ích" mô hình phù hợp GUID:

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

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var value = (string)JToken.Load(reader); 
     if (value == null) 
      return null; 
     if (value.Length == 0) 
      return new byte[0]; 
     return Convert.FromBase64String(value); 
    } 

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

Và sau đó, để thiết lập nó trên toàn cầu:

 JsonConvert.DefaultSettings =() => new JsonSerializerSettings 
     { 
      Converters = new List<JsonConverter> { new ByteConverter() } 
     }; 

workaround này khôi phục deserialization đúng cho mảng byte.

+0

Trình diễn tuyệt vời về lỗi và giải pháp tốt được đề xuất. +1 :) –

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