2013-03-05 14 views
22

Używam JSON.net do serializacji niektórych obiektów między C# i JavaScript. Dane JSON są przesyłane za pośrednictwem WebSocket między aplikacją .NET i przeglądarką.Jak serializować bajt [] jako prosty JSON Array, a nie jako base64 w JSON.net?

W strukturze danych jest kilka pól byte[], Te pola chcę również jako Array w JavaScript.

Jak można przekształcić kod C# byte[] w prostą tablicę JSON, taką jak [ 0 , 1 , 254, 255 ] zamiast łańcucha base64?

Odpowiedz

11

Najprostszy sposób można myślę o to, aby przekształcić tablicę bajtów do tablicy liczb całkowitych, jak:

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

ten nie wymaga żadnej specjalnej obsługi biblioteki JSON lub dowolny niestandardowy serializacji lub coś podobnego że.

EDIT: Oznaczałoby to konieczność dostosowania obiektu danych do obsługi różnego typu. Może:

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

Więc może to nie jest najprostszy - w zależności od tego, ile rzeczy masz do serializacji

+0

Uwielbiam rozwiązanie "int Array". Praca jest świetna i łatwa do wdrożenia. Bardzo dziękuję za tę podpowiedź. – Marcus

+0

Bravo. Bajt pasuje do int, a całe int [] jest tablicą bajtów. WCF z powiązaniem JSON na drugim końcu może wykonać szeregowy DTO JSON z właściwością byte [] i bezpiecznie deserializować go bez żadnych niestandardowych formaterów lub dekodowania base64/zapisu Stream. Rozmiar serializowanego JSON jest całkiem wspaniały, ale działa! –

+0

Używa jednak 8-krotnej pamięci tablicy bajtów, więc nie zawsze jest to wykonalne rozwiązanie. – FINDarkside

40

JSON.NET jest wybranie BinaryConverter do odczytu i zapisu tablicę bajtów. widać the source że wykorzystuje operację WriteValue od klasy JsonWriter z tablicy bajtów, które powoduje ich być zapisywane jako base-64.

Aby to zmodyfikować, można napisać własny konwerter, który odczytuje i zapisuje tablicę w formacie można oczekiwać:

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[]); 
    } 
} 

byłoby to wykorzystać stosując JsonConverterAttribute członkowi:

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

Punkty premiowe za zapewnienie rzeczywistej klasy ByteArrayConverter! Wystąpił jednak niewielki błąd. Ponieważ już używasz JsonWriter, nie ma potrzeby ręcznego dodawania przecinka, więc możesz po prostu usunąć tę część: , jeśli (i! = Data.Length) { writer.WriteRaw (","); } przeciwnym razie tablica będzie wyglądać następująco: [12, 54, 32,, 8] –

+0

To działa dobrze i wydaje się być sposobem interfejs json miał być stosowany. –

Powiązane problemy