2013-03-05 19 views
22

Tôi sử dụng JSON.net để tuần tự hóa một số đối tượng giữa C# và JavaScript. Dữ liệu JSON được truyền qua WebSocket giữa ứng dụng .NET và trình duyệt.Làm thế nào để tuần tự hóa byte [] thành JSON Array đơn giản và không phải là base64 trong JSON.net?

Trong cấu trúc dữ liệu có một số trường byte[], tôi cũng muốn các trường này dưới dạng Array trong JavaScript.

Làm cách nào để tuần tự hóa C# byte[] thành một mảng JSON đơn giản như [ 0 , 1 , 254, 255 ] thay vì chuỗi base64?

Trả lời

11

đơn giản nhất cách tôi có thể nghĩ đến là để chuyển đổi mảng byte vào một mảng số nguyên, như:

var intArray = byteArray.Select(b => (int)b).ToArray(); 

này sẽ không yêu cầu bất kỳ xử lý đặc biệt của thư viện JSON, hoặc bất kỳ serialization tùy chỉnh hoặc bất cứ điều gì như cái đó.

EDIT: Điều này có nghĩa là phải tùy chỉnh đối tượng dữ liệu của bạn để xử lý loại khác. Có thể:

public class CustomFoo : Foo 
{ 
    // SomeBytesHere is a byte[] in the base class 
    public new int[] SomeBytesHere { get;set; } 
} 

Vì vậy, có lẽ nó không phải là đơn giản nhất - tùy thuộc vào bao nhiêu thứ bạn phải serialize

+0

Tôi thích giải pháp 'int Array'. Công việc tuyệt vời và đơn giản để thực hiện. Rất cám ơn vì gợi ý đó. – Marcus

+0

Bravo. Một byte phù hợp với một int, và toàn bộ int [] là một mảng các byte. WCF với một ràng buộc JSON ở đầu kia có thể lấy một DTO được tuần tự hóa JSON với thuộc tính byte [] và an toàn deserialize nó mà không có bất kỳ trình định dạng tùy chỉnh hoặc giải mã base64/ghi dòng. Kích thước của JSON được tuần tự hóa là khá tuyệt vời, nhưng nó hoạt động! –

+0

Nó sẽ sử dụng 8 lần bộ nhớ của mảng byte, vì vậy không phải luôn luôn là một giải pháp khả thi. – FINDarkside

40

JSON.NET là chọn BinaryConverter để đọc và viết một mảng byte. Bạn có thể thấy trong the source rằng nó sử dụng hoạt động WriteValue trên lớp JsonWriter với mảng byte khiến chúng được ghi thành Base-64.

Để sửa đổi này, bạn có thể viết Chuyển đổi riêng của bạn mà đọc và viết một mảng trong các định dạng mà bạn mong đợi:

public class ByteArrayConverter : JsonConverter 
{ 
    public override void WriteJson(
     JsonWriter writer, 
     object value, 
     JsonSerializer serializer) 
    { 
     if (value == null) 
     { 
      writer.WriteNull(); 
      return; 
     } 

     byte[] data = (byte[])value; 

     // Compose an array. 
     writer.WriteStartArray(); 

     for (var i = 0; i < data.Length; i++) 
     { 
      writer.WriteValue(data[i]); 
     } 

     writer.WriteEndArray(); 
    } 

    public override object ReadJson(
     JsonReader reader, 
     Type objectType, 
     object existingValue, 
     JsonSerializer serializer) 
    { 
     if (reader.TokenType == JsonToken.StartArray) 
     { 
      var byteList = new List<byte>(); 

      while (reader.Read()) 
      { 
       switch (reader.TokenType) 
       { 
        case JsonToken.Integer: 
         byteList.Add(Convert.ToByte(reader.Value)); 
         break; 
        case JsonToken.EndArray: 
         return byteList.ToArray(); 
        case JsonToken.Comment: 
         // skip 
         break; 
        default: 
         throw new Exception(
         string.Format(
          "Unexpected token when reading bytes: {0}", 
          reader.TokenType)); 
       } 
      } 

      throw new Exception("Unexpected end when reading bytes."); 
     } 
     else 
     { 
      throw new Exception(
       string.Format(
        "Unexpected token parsing binary. " 
        + "Expected StartArray, got {0}.", 
        reader.TokenType)); 
     } 
    } 

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

Bạn sẽ sử dụng này bằng cách áp dụng JsonConverterAttribute cho thành viên:

[JsonConverter(typeof(ByteArrayConverter))] 
public byte[] Data { get; set; } 
+1

Điểm thưởng để cung cấp lớp ByteArrayConverter thực tế! Tuy nhiên, có một lỗi nhỏ. Bởi vì bạn đã sử dụng JsonWriter, không cần phải thêm dấu phẩy theo cách thủ công, vì vậy bạn chỉ có thể xóa phần này: nếu (i! = Data.Length) { writer.WriteRaw (","); } Nếu không mảng của bạn sẽ trông như thế này: [12,, 54,, 32,, 8] –

+0

Điều này hoạt động tốt và có vẻ là cách giao diện json được sử dụng. –