791 Stimmen

Binäre Daten in JSON-String. Etwas Besseres als Base64

があります。 JSON-Format unterstützt von Haus aus keine Binärdaten. Die binären Daten müssen escaped werden, damit sie in ein String-Element (d. h. null oder mehr Unicode-Zeichen in Anführungszeichen mit Backslash-Escapes) in JSON eingefügt werden können.

Eine offensichtliche Methode zur Entschlüsselung von Binärdaten ist die Verwendung von Base64. Base64 ist jedoch mit einem hohen Verarbeitungsaufwand verbunden. Außerdem werden 3 Bytes in 4 Zeichen expandiert, was zu einer Erhöhung der Datengröße um etwa 33 % führt.

Ein Anwendungsfall hierfür ist der Entwurf v0.8 des Spezifikation der CDMI-Wolkenspeicher-API . Sie erstellen Datenobjekte über einen REST-Webservice unter Verwendung von JSON, z.B.

PUT /MyContainer/BinaryObject HTTP/1.1
Host: cloud.example.com
Accept: application/vnd.org.snia.cdmi.dataobject+json
Content-Type: application/vnd.org.snia.cdmi.dataobject+json
X-CDMI-Specification-Version: 1.0
{
    "mimetype" : "application/octet-stream",
    "metadata" : [ ],
    "value" :   "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz
    IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg
    dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu
    dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo
    ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=",
}

Gibt es bessere Möglichkeiten und Standardmethoden zur Kodierung von Binärdaten in JSON-Strings?

51 Stimmen

Für den Upload: Sie machen es nur einmal, also ist es keine große Sache. Für den Download: Sie werden überrascht sein, wie gut base64 komprimiert unter gzip Wenn Sie also gzip auf Ihrem Server aktiviert haben, ist das wahrscheinlich auch in Ordnung.

6 Stimmen

Eine weitere würdige Lösung msgpack.org für die Hardcore-Nerds: github.com/msgpack/msgpack/blob/master/spec.md

6 Stimmen

@cloudfeet, Einmal pro Benutzer pro Aktion . Eine sehr große Sache.

4voto

Kamil Kiełczewski Punkte 69048

Vertiefung

Ich grabe ein wenig mehr (während der Umsetzung von Basis128 ), und stellen Sie fest, dass wenn wir Zeichen senden, deren Ascii-Codes größer als 128 sind, sendet der Browser (Chrome) tatsächlich ZWEI Zeichen (Bytes) statt einem :( . Der Grund dafür ist, dass JSON standardmäßig utf8-Zeichen verwendet, für die Zeichen mit Ascii-Codes über 127 durch zwei Bytes kodiert werden, was von chmike Antwort. Ich habe den Test folgendermaßen durchgeführt: Geben Sie in der URL-Leiste von Chrome ein chrome://net-export/ Wählen Sie "Include raw bytes", starten Sie die Aufzeichnung, senden Sie POST-Anfragen (mit dem Snippet unten), beenden Sie die Aufzeichnung und speichern Sie die json-Datei mit den Rohdaten der Anfragen. Dann schauen wir in diese json-Datei:

  • Wir können unsere base64-Anfrage finden, indem wir den String 4142434445464748494a4b4c4d4e dies ist die Hex-Codierung von ABCDEFGHIJKLMN und wir werden sehen, dass "byte_count": 639 für sie.
  • Wir können unsere obige127 Anfrage finden, indem wir den String C2BCC2BDC380C381C382C383C384C385C386C387C388C389C38AC38B dies sind die utf8-Codes der Zeichen in request-hex ¼½ÀÁÂÃÄÅÆÇÈÉÊË (die ascii-Hex-Codes dieser Zeichen sind jedoch c1c2c3c4c5c6c7c8c9cacbcccdce ). Die Website "byte_count": 703 so ist es 64bytes länger als base64 Anfrage, weil Zeichen mit ascii-Codes über 127 sind Code von 2 Bytes in der Anfrage :(

Wir haben also in der Tat keinen Gewinn mit dem Senden von Zeichen mit Codes >127 :( . Für base64-Zeichenfolgen beobachten wir kein solch negatives Verhalten (wahrscheinlich auch für base85 - ich überprüfe es nicht) - aber vielleicht ist eine Lösung für dieses Problem das Senden von Daten im binären Teil von POST multipart/form-data, beschrieben in Ælex Antwort (normalerweise brauchen wir in diesem Fall jedoch überhaupt keine Grundkodierung zu verwenden...).

Der alternative Ansatz kann sich darauf stützen, zwei Bytes Datenanteil in ein gültiges utf8-Zeichen umzuwandeln, indem man es mit etwas wie Basis65280 / Basis65k aber wahrscheinlich wäre es weniger effektiv als base64 aufgrund von utf8-Spezifikation ...

function postBase64() {
  let formData = new FormData();
  let req = new XMLHttpRequest();

  formData.append("base64ch", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
  req.open("POST", '/testBase64ch');
  req.send(formData);
}

function postAbove127() {
  let formData = new FormData();
  let req = new XMLHttpRequest();

  formData.append("above127", "¼½ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüý");
  req.open("POST", '/testAbove127');
  req.send(formData);
}

<button onclick=postBase64()>POST base64 chars</button>
<button onclick=postAbove127()>POST chars with codes>127</button>

3voto

a paid nerd Punkte 29564

( Bearbeitung 7 Jahre später: Google Gears ist verschwunden. Ignorieren Sie diese Antwort).


Das Google Gears-Team ist auf das Problem der fehlenden binären Datentypen gestoßen und hat versucht, es zu lösen:

Blob-API

JavaScript hat einen eingebauten Datentyp für Textstrings, aber keinen für binäre Daten. Das Blob-Objekt versucht, diese Einschränkung zu beheben.

Vielleicht können Sie das irgendwie einflechten.

0 Stimmen

Also, was ist der Status von Blobs in Javascript und json? Wurden sie fallen gelassen?

1 Stimmen

w3.org/TR/FileAPI/#blob-section Nicht so performant wie base64 für Raum, wenn Sie nach unten scrollen Sie finden, dass es mit utf8 Karte kodiert (wie die eine der Option von Hobbs Antwort gezeigt). Und keine json Unterstützung, so weit ich weiß

2voto

Martin Kersten Punkte 5459

Ich möchte die Diskussion nur um den Aspekt der Ressourcen und der Komplexität erweitern. Bei der Verwendung von PUT/POST und PATCH für die Speicherung neuer Ressourcen und deren Änderung sollte man bedenken, dass der Inhaltstransfer eine exakte Repräsentation des gespeicherten Inhalts ist, den man durch eine GET-Operation erhält.

Eine mehrteilige Nachricht wird oft als Rettung eingesetzt, aber der Einfachheit halber und bei komplexeren Aufgaben ziehe ich es vor, den Inhalt als Ganzes zu vermitteln. Das ist selbsterklärend und einfach.

Und ja, JSON ist etwas lähmend, aber letztendlich ist JSON selbst sehr ausführlich. Und der Overhead der Abbildung auf BASE64 ist ein Weg zu klein.

Bei der korrekten Verwendung von mehrteiligen Nachrichten muss man entweder das zu sendende Objekt zerlegen, einen Eigenschaftspfad als Parametername für die automatische Kombination verwenden oder ein anderes Protokoll/Format erstellen, um nur die Nutzlast auszudrücken.

Auch der BSON-Ansatz wird nicht so breit und einfach unterstützt, wie man es sich wünschen würde.

Im Grunde genommen vermissen wir hier nur etwas, aber die Einbettung von Binärdaten als base64 ist gut etabliert und der richtige Weg, es sei denn, Sie haben wirklich die Notwendigkeit erkannt, die echte Binärübertragung durchzuführen (was kaum der Fall ist).

0 Stimmen

Das Senden und Empfangen von mehrteiligen Nachrichten in .NET macht keinen Spaß, ist übermäßig komplex und abstrakt. Es ist einfacher, einfach rohe Strings zu senden, damit Sie tatsächlich debuggen und sehen können, was gesendet und empfangen wird, und den String in ein JSON-Objekt oder ein Klassenobjekt auf dem Server zu konvertieren. Base64 direkt im JSON- oder XML-String ist einfach und gut zu debuggen.

1voto

Richie Bendall Punkte 5294

In Node.js können Sie einen Buffer in eine Zeichenkette umwandeln und zurück, ohne dass sich etwas ändert:

const serialized = buffer.toString("binary")
const deserialized = Buffer.from(serialized, "binary")

Wenn Sie mehr Zuverlässigkeit auf Kosten der Größe wünschen, ersetzen Sie "binary" mit "base64"

0 Stimmen

Getestet und genehmigt?

0 Stimmen

Wenn Sie 100%ige Zuverlässigkeit wünschen, ersetzen Sie "binary" durch "base64".

0voto

Atlas Sullivan Punkte 69

Eine andere, neuere Idee ist die Verschlüsselung der Daten über uuencode . Es ist ein meist veraltetes, aber es pourrait immer noch eine Alternative sein. (Wenn auch vielleicht keine ernsthafte.)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X