webentwicklung-frage-antwort-db.com.de

Wie man Byte [] als einfaches JSON-Array und nicht als base64 in JSON.net serialisiert?

Ich benutze JSON.net, um einige Objekte zwischen C # und JavaScript zu serialisieren. Die JSON-Daten werden über WebSocket zwischen .NET und der Browseranwendung übertragen. 

In der Datenstruktur gibt es einige byte[]-Felder, ich möchte diese Felder auch als Array in JavaScript.

Wie kann ich einen C # byte[] in ein einfaches JSON-Array wie [ 0 , 1 , 254, 255 ] anstelle einer base64-Zeichenfolge serialisieren?

24
Marcus

Der einfachste Weg, den ich mir vorstellen kann, ist das Byte-Array in ein Integer-Array umzuwandeln, wie:

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

Dies erfordert keine besondere Behandlung der JSON-Bibliothek, keine benutzerdefinierte Serialisierung oder ähnliches.

EDIT: Dies würde bedeuten, dass Sie Ihr Datenobjekt anpassen müssen, um mit dem anderen Typ umzugehen. Könnte sein:

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

Also ist es vielleicht nicht das einfachste - abhängig davon, wie viel Sie serialisieren müssen

12
Joe Enos

JSON.NET wählt BinaryConverter aus, um ein Array von Bytes zu lesen und zu schreiben. Sie können in der Quelle sehen, dass sie die WriteValue-Operation für die JsonWriter-Klasse mit dem Byte-Array verwendet, wodurch sie als Base-64 geschrieben werden.

Um dies zu ändern, können Sie einen eigenen Konverter schreiben, der ein Array im erwarteten Format liest und schreibt:

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

Sie würden dies verwenden, indem Sie JsonConverterAttribute auf das Member anwenden:

[JsonConverter(typeof(ByteArrayConverter))]
public byte[] Data { get; set; }
50
Paul Turner

Ref meine Antwort , JSON.net kann die Serialisierung für alle Einstellungen anstelle von Attributen in der Eigenschaft anpassen.

Sie können ihn leicht von base64 in number array ändern. Schreiben Sie einfach einen csv-Wert in eckige Klammern.

0
IlPADlI