ข้อมูลไบนารีในสตริง JSON สิ่งที่ดีกว่า Base64


614

รูปแบบ JSONกำเนิดไม่สนับสนุนข้อมูลไบนารี ข้อมูลไบนารีจะต้องมีการหลบหนีเพื่อให้สามารถวางลงในองค์ประกอบสตริง (เช่นศูนย์หรือมากกว่าตัวอักษร Unicode ในเครื่องหมายคำพูดคู่โดยใช้เครื่องหมายทับขวา) ใน JSON

วิธีที่ชัดเจนในการหลีกเลี่ยงข้อมูลไบนารีคือการใช้ Base64 อย่างไรก็ตาม Base64 มีค่าใช้จ่ายในการประมวลผลสูง นอกจากนี้ยังขยาย 3 ไบต์เป็น 4 ตัวอักษรซึ่งนำไปสู่การเพิ่มขนาดข้อมูลประมาณ 33%

กรณีการใช้งานหนึ่งสำหรับเรื่องนี้คือร่าง v0.8 ของCDMI เมฆข้อกำหนดการจัดเก็บ คุณสร้างวัตถุข้อมูลผ่าน REST-Webservice โดยใช้ JSON เช่น

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=",
}

มีวิธีที่ดีกว่าและวิธีมาตรฐานในการเข้ารหัสข้อมูลไบนารีลงในสตริง JSON หรือไม่


30
สำหรับการอัปโหลด: คุณทำเพียงครั้งเดียวดังนั้นจึงไม่ใช่เรื่องใหญ่ สำหรับการดาวน์โหลดคุณอาจประหลาดใจที่ base64 บีบอัดใต้ gzip ได้ดีเพียงใดดังนั้นหากคุณเปิดใช้งาน gzip บนเซิร์ฟเวอร์ของคุณคุณก็อาจตกลง
cloudfeet

2
อีกโซลูชันที่คุ้มค่าสำหรับmsgpack.orgสำหรับผู้ไม่ยอมใครง่ายๆที่ไม่
พึงประสงค์

2
@cloudfeet, เมื่อต่อผู้ใช้ต่อการกระทำ เรื่องใหญ่มาก
Pacerier

2
โปรดทราบว่าตัวละครโดยทั่วไปจะมี2 ไบต์หน่วยความจำแต่ละ ดังนั้น base64 อาจให้ + 33% (4/3) ค่าใช้จ่ายในสาย แต่การวางข้อมูลบนลวดเรียกมันและใช้มันจะต้องมี + 166% (8/3) ค่าใช้จ่าย ตัวพิมพ์เล็ก - ใหญ่: หากสตริง Javascript มีความยาวสูงสุด 100k chars คุณสามารถแสดงข้อมูล 37.5k ไบต์โดยใช้ base64 ไม่ใช่ 75k ไบต์ของข้อมูล ตัวเลขเหล่านี้อาจเป็นปัญหาคอขวดในหลาย ๆ ส่วนของแอปพลิเคชั่นJSON.parseฯลฯ ......
Pacerier

5
@Pacerier "โดยทั่วไปแล้วหน่วยความจำ 2 ไบต์ [ต่อตัวอักษร]" ไม่ถูกต้อง ตัวอย่างเช่น v8 มีสตริง OneByte และ TwoByte สตริงสองไบต์ใช้เมื่อจำเป็นเท่านั้นเพื่อหลีกเลี่ยงการใช้หน่วยความจำที่ผิดปกติ Base64 สามารถเข้ารหัสได้ด้วยสตริงหนึ่งไบต์
ZachB

คำตอบ:


459

มี 94 อักขระ Unicode ซึ่งสามารถแสดงเป็นหนึ่งไบต์ตามข้อมูลจำเพาะ JSON (หาก JSON ของคุณถูกส่งเป็น UTF-8) โดยที่ในใจฉันคิดว่าสิ่งที่ดีที่สุดที่คุณสามารถทำได้คือ space-wise คือbase85ซึ่งแสดงถึงสี่ไบต์เป็นตัวอักษรห้าตัว อย่างไรก็ตามนี่เป็นเพียงการปรับปรุง 7% จากฐาน 64 มันมีราคาแพงกว่าในการคำนวณและการติดตั้งใช้งานน้อยกว่าฐาน 64 ดังนั้นจึงอาจไม่ใช่การชนะ

คุณสามารถแมปอินพุตไบต์ทุกตัวกับอักขระที่สอดคล้องกันใน U + 0000-U + 00FF จากนั้นทำการเข้ารหัสขั้นต่ำที่มาตรฐาน JSON กำหนดเพื่อส่งผ่านอักขระเหล่านั้น ข้อดีของที่นี่ก็คือการถอดรหัสที่ต้องการนั้นไม่มีอะไรมากไปกว่าฟังก์ชั่นบิวอินในตัว แต่ประสิทธิภาพของพื้นที่ไม่ดี - การขยายตัว 105% (ถ้าอินพุตไบท์ทั้งหมดมีแนวโน้มเท่ากัน) เทียบกับ 25% สำหรับ base85 หรือ 33% สำหรับ base64

คำตัดสินรอบชิงชนะเลิศ: base64 ชนะในความคิดของฉันเพราะมันเป็นเรื่องธรรมดาง่ายและไม่เลวร้ายพอที่จะรับประกันการเปลี่ยน

ดูเพิ่มเติม: Base91และBase122


5
รอว่าจะใช้แค่ byte จริงอย่างไรในขณะที่เข้ารหัสอักขระเครื่องหมายคำพูดเป็นการขยายตัว 105% และ base64 เพียง 33%? ไม่ใช่ฐาน 64 133%?
jjxtra

17
Base91 เป็นแนวคิดที่ไม่ดีสำหรับ JSON เนื่องจากมีเครื่องหมายคำพูดเป็นตัวอักษร ในกรณีที่เลวร้ายที่สุด (เอาต์พุตอัญประกาศทั้งหมด) หลังจากการเข้ารหัส JSON จะเป็น 245% ของเพย์โหลดดั้งเดิม
jarnoh

25
Python 3.4 ประกอบด้วยbase64.b85encode()และb85decode()ตอนนี้ การวัดระยะเวลาการเข้ารหัส + ถอดรหัสอย่างง่ายแสดงให้เห็นว่า b85 ช้ากว่า b64 มากกว่า 13 เท่า ดังนั้นเราจึงชนะได้ขนาด 7% แต่สูญเสียประสิทธิภาพถึง 1300%
Pieter Ennes

3
@hobbs JSONระบุว่าจะต้องหลีกเลี่ยงอักขระควบคุม RFC20 ส่วน 5.2กำหนดDELให้เป็นอักขระควบคุม
Tino

2
@Tino ECMA-404 แสดงรายการอักขระที่ต้องหลบหนีโดยเฉพาะ: เครื่องหมายคำพูดคู่ U + 0022, เครื่องหมายแบ็กสแลช U + 005C และ "อักขระควบคุม U + 0000 ถึง U + 001F"
ฮอบส์

249

ฉันพบปัญหาเดียวกันและคิดว่าฉันจะแบ่งปันวิธีแก้ปัญหา: multipart / form-data

โดยการส่งแบบฟอร์ม multipart คุณส่งเป็นครั้งแรกที่สายของคุณJSON meta ข้อมูลแล้วแยกส่งเป็นไบนารีดิบ (ภาพที่ (s), wavs ฯลฯ ) การจัดทำดัชนีโดยDisposition เนื้อหาชื่อ

นี่คือบทแนะนำที่ดีเกี่ยวกับวิธีการทำใน obj-c และนี่คือบทความบล็อกที่อธิบายวิธีแบ่งพาร์ติชันข้อมูลสตริงด้วยขอบเขตแบบฟอร์มและแยกมันออกจากข้อมูลไบนารี

การเปลี่ยนแปลงเพียงอย่างเดียวที่คุณต้องทำคืออยู่ที่ฝั่งเซิร์ฟเวอร์ คุณจะต้องรวบรวมข้อมูลเมตาของคุณซึ่งควรอ้างอิงข้อมูลไบนารี POST'ed อย่างเหมาะสม (โดยใช้ขอบเขตเนื้อหาการจัดการ)

จริงอยู่ที่มันต้องใช้งานเพิ่มเติมในฝั่งเซิร์ฟเวอร์ แต่ถ้าคุณกำลังส่งภาพจำนวนมากหรือภาพขนาดใหญ่นี้มีมูลค่ามัน รวมสิ่งนี้กับการบีบอัด gzip หากคุณต้องการ

IMHO ส่งข้อมูลที่เข้ารหัส base64 คือแฮ็ค RFC multipart / form-data ถูกสร้างขึ้นสำหรับปัญหาเช่นนี้: การส่งข้อมูลไบนารีร่วมกับข้อความหรือ meta-data


4
โดยวิธีการที่ Google Drive API ทำเช่นนี้: developers.google.com/drive/v2/reference/files/update#examples
Mathias Conradt

2
ทำไมคำตอบนี้จึงต่ำลงเมื่อใช้คุณลักษณะดั้งเดิมแทนที่จะพยายามบีบหมุดกลม (ไบนารี) ลงในรูสี่เหลี่ยม (ASCII)? ...
Mark K Cowan

5
การส่งข้อมูลที่เข้ารหัส base64 เป็นแฮ็คดังนั้นจึงเป็น multipart / form-data แม้แต่บทความในบล็อกที่คุณเชื่อมโยงก็อ่านว่าด้วยการใช้มัลติเท็กซ์ประเภทเนื้อหา / แบบฟอร์มข้อมูลคุณระบุว่าสิ่งที่คุณส่งเป็นรูปแบบจริง แต่มันไม่ใช่ ดังนั้นฉันคิดว่าการแฮ็ก base64 ไม่เพียง แต่ง่ายต่อการติดตั้งเท่านั้น แต่ยังมีความน่าเชื่อถือมากกว่าที่ฉันเคยเห็นบางไลบรารี (สำหรับ Python ตัวอย่าง) ซึ่งมีประเภทเนื้อหาหลายส่วน / ฟอร์มข้อมูลแบบฮาร์ดโค้ด
t3chb0t

4
@ t3chb0t สื่อชนิดหลายส่วน / แบบฟอร์มข้อมูลเกิดมาเพื่อส่งผ่านข้อมูลแบบฟอร์ม แต่วันนี้มีการใช้กันอย่างแพร่หลายนอกโลก HTTP / HTML โดยเฉพาะอย่างยิ่งในการเข้ารหัสเนื้อหาอีเมล วันนี้มีการเสนอเป็นรูปแบบการเข้ารหัสทั่วไป tools.ietf.org/html/rfc7578
lorenzo

3
@MarkKCowan อาจเป็นเพราะในขณะนี้มีประโยชน์ต่อวัตถุประสงค์ของคำถาม แต่ก็ไม่ตอบคำถามตามที่ถามซึ่งมีประสิทธิภาพ "ไบนารีค่าโสหุ้ยต่ำเป็นการเข้ารหัสข้อความสำหรับใช้ใน JSON" คำตอบนี้ทิ้ง JSON อย่างสมบูรณ์
Chinoto Vokro

34

ปัญหาของ UTF-8 คือมันไม่ได้เป็นการเข้ารหัสที่มีประสิทธิภาพที่สุดในพื้นที่ นอกจากนี้บางลำดับไบนาร์ไบน์สุ่มเป็นการเข้ารหัส UTF-8 ที่ไม่ถูกต้อง ดังนั้นคุณจึงไม่สามารถตีความลำดับไบนารีแบบสุ่มเป็นข้อมูล UTF-8 บางตัวเพราะมันจะเป็นการเข้ารหัสแบบ UTF-8 ที่ไม่ถูกต้อง ประโยชน์ของข้อ จำกัด นี้ในการเข้ารหัส UTF-8 คือมันทำให้มีความแข็งแกร่งและเป็นไปได้ในการค้นหาตัวอักษรหลายไบต์เริ่มต้นและสิ้นสุดสิ่งที่ไบต์ที่เราเริ่มมองหา

ดังนั้นหากการเข้ารหัสค่าไบต์ในช่วง [0..127] จะต้องการเพียงหนึ่งไบต์ในการเข้ารหัส UTF-8 การเข้ารหัสค่าไบต์ในช่วง [128..255] จะต้องมี 2 ไบต์! ยิ่งกว่านั้น ใน JSON ตัวอักษรควบคุม "และ \ ไม่ได้รับอนุญาตให้ปรากฏในสตริงดังนั้นข้อมูลไบนารีจะต้องมีการเข้ารหัสการแปลงบางอย่างอย่างถูกต้อง

มาดูกัน. ถ้าเราสมมติว่ามีการกระจายค่าสุ่มแบบสุ่มในข้อมูลไบนารี่ของเราโดยเฉลี่ยครึ่งหนึ่งของไบต์จะถูกเข้ารหัสในหนึ่งไบต์และอีกครึ่งหนึ่งเป็นสองไบต์ ข้อมูลไบนารีที่เข้ารหัส UTF-8 จะมีขนาด 150% ของขนาดเริ่มต้น

การเข้ารหัส Base64 เติบโตเพียง 133% ของขนาดเริ่มต้น ดังนั้นการเข้ารหัส Base64 จึงมีประสิทธิภาพมากกว่า

การใช้การเข้ารหัสฐานอื่นจะทำอย่างไร? ใน UTF-8 การเข้ารหัสค่า 128 ASCII เป็นพื้นที่ที่มีประสิทธิภาพที่สุด ใน 8 บิตคุณสามารถเก็บ 7 บิต ดังนั้นถ้าเราตัดข้อมูลไบนารี่ออกเป็น 7 บิตเพื่อเก็บไว้ในแต่ละไบต์ของสตริงที่เข้ารหัส UTF-8 ข้อมูลที่เข้ารหัสจะเติบโตเพียง 114% ของขนาดเริ่มต้น ดีกว่า Base64 น่าเสียดายที่เราไม่สามารถใช้เคล็ดลับง่าย ๆ นี้ได้เนื่องจาก JSON ไม่อนุญาตให้ใช้ตัวอักษร ASCII บางตัว อักขระควบคุม 33 ตัวของ ASCII ([0..31] และ 127) และต้องไม่รวม "และ \" สิ่งนี้ทำให้เรามีเพียง 128-35 = 93 ตัวอักษร

ในทางทฤษฎีเราสามารถกำหนดการเข้ารหัส Base93 ซึ่งจะเพิ่มขนาดการเข้ารหัสเป็น 8 / log2 (93) = 8 * log10 (2) / log10 (93) = 122% แต่การเข้ารหัส Base93 จะไม่สะดวกเท่ากับการเข้ารหัส Base64 Base64 จำเป็นต้องตัดลำดับไบต์เข้าใน 6 บิตซึ่งการดำเนินการ bitwise ง่ายทำงานได้ดี ข้าง 133% ไม่มากไปกว่า 122%

นี่คือเหตุผลที่ฉันมาถึงข้อสรุปทั่วไปว่า Base64 เป็นตัวเลือกที่ดีที่สุดในการเข้ารหัสข้อมูลไบนารีใน JSON คำตอบของฉันนำเสนอเหตุผลสำหรับมัน ฉันเห็นด้วยว่ามันไม่ได้น่าสนใจมากนักจากมุมมองด้านประสิทธิภาพ แต่ก็ควรพิจารณาถึงประโยชน์ของการใช้ JSON ด้วยเพราะมันเป็นการนำเสนอสตริงที่มนุษย์สามารถอ่านได้ง่ายต่อการจัดการในภาษาการเขียนโปรแกรมทั้งหมด

หากประสิทธิภาพมีความสำคัญมากกว่าการเข้ารหัสแบบไบนารีที่แท้จริงควรพิจารณาว่าเป็นการแทนที่ JSON แต่ด้วย JSON ข้อสรุปของฉันคือ Base64 ดีที่สุด


แล้ว Base128 จะปล่อยให้ JSON serializer หลุด "และ \? ฉันคิดว่ามันสมเหตุสมผลที่จะคาดหวังให้ผู้ใช้ใช้ json parser ในการใช้งาน
jcalfee314

1
@ jcalfee314 เป็นไปไม่ได้เนื่องจากไม่อนุญาตให้ใช้อักขระที่มีรหัส ASCII ต่ำกว่า 32 ในสตริง JSON การเข้ารหัสที่มีฐานระหว่าง 64 ถึง 128 ได้ถูกกำหนดไว้แล้ว แต่การคำนวณที่ต้องการนั้นสูงกว่า base64 การเพิ่มขนาดของข้อความที่เข้ารหัสไม่คุ้มค่า
chmike

หากการโหลดภาพจำนวนมากใน base64 (สมมติว่า 1,000) หรือโหลดผ่านการเชื่อมต่อที่ช้ามาก base85 หรือ base93 จะต้องจ่ายเงินเพื่อลดทอนสัญญาณเครือข่าย (w / หรือ w / o gzip) หรือไม่? ฉันอยากรู้ว่ามีจุดที่ข้อมูลขนาดกะทัดรัดมากขึ้นจะทำให้กรณีสำหรับหนึ่งในวิธีการทางเลือก
vol7ron

ฉันสงสัยว่าความเร็วในการคำนวณสำคัญกว่าเวลาการส่ง ควรมีการคำนวณรูปภาพล่วงหน้าไว้ที่ฝั่งเซิร์ฟเวอร์ อย่างไรก็ตามข้อสรุปคือ JSON ไม่ดีสำหรับข้อมูลไบนารี
chmike

เรื่อง "การเข้ารหัส Base64 เติบโตเพียง 133% ของขนาดเริ่มต้นดังนั้นการเข้ารหัส Base64 จึงมีประสิทธิภาพมากขึ้น " นี่เป็นความผิดอย่างสมบูรณ์เพราะตัวอักษรโดยทั่วไปจะมี 2 ไบต์ ดูรายละเอียดเพิ่มเติมได้ที่stackoverflow.com/questions/1443158/…
Pacerier

34

BSON (Binary JSON) อาจใช้งานได้สำหรับคุณ http://en.wikipedia.org/wiki/BSON

แก้ไข:. FYI. ห้องสมุดjson.netรองรับการอ่านและการเขียน bson หากคุณกำลังมองหารักเซิร์ฟเวอร์ C #


1
"ในบางกรณี BSON จะใช้พื้นที่มากกว่า JSON เนื่องจากคำนำหน้ายาวและดัชนีอาเรย์ชัดเจน" en.wikipedia.org/wiki/BSON
Pawel Cioch

ข่าวดี: BSON สนับสนุนประเภทต่างๆเช่น Binary, Datetime และอื่น ๆ เล็กน้อย (มีประโยชน์อย่างยิ่งถ้าคุณใช้ MongoDB) ข่าวร้าย: มันคือการเข้ารหัสไบนารี่ไบท์ ... ดังนั้นมันจึงไม่ใช่คำตอบของ OP อย่างไรก็ตามมันจะมีประโยชน์มากกว่าช่องทางที่รองรับไบนารีแบบดั้งเดิมเช่นข้อความ RabbitMQ, ข้อความ ZeroMQ หรือซ็อกเก็ต TCP หรือ UDP แบบกำหนดเอง
Dan H

19

หากคุณจัดการกับปัญหาแบนด์วิดท์ให้ลองบีบอัดข้อมูลที่ฝั่งไคลเอ็นต์ก่อนจากนั้นตามด้วยหมายเลข 64

ตัวอย่างที่ดีของเวทย์มนตร์ดังกล่าวอยู่ที่http://jszip.stuartk.co.uk/และการสนทนาเพิ่มเติมในหัวข้อนี้อยู่ที่การนำ JavaScript ของ Gzip ไปใช้


2
นี่คือการใช้งานจาวาสคริปต์ zip ซึ่งอ้างว่ามีประสิทธิภาพที่ดีขึ้น: zip.js
Janus Troelsen

โปรดทราบว่าคุณสามารถ (และควร) ยังคงบีบอัดหลังจากนั้นเช่นกัน (โดยทั่วไปผ่านContent-Encoding) เนื่องจากฐาน 64 บีบอัดได้ค่อนข้างดี
Mahmoud Al-Qudsi

@ MahmoudAl-Qudsi คุณหมายความว่าคุณ base64 (zip (base64 (zip (data)))))? ฉันไม่แน่ใจว่าการเพิ่ม zip อื่นแล้ว base64 (เพื่อให้สามารถส่งเป็นข้อมูล) เป็นความคิดที่ดี
andrej

18

yEnc อาจทำงานให้คุณ:

http://en.wikipedia.org/wiki/Yenc

"yEnc เป็นรูปแบบการเข้ารหัสแบบ binary-to-text สำหรับการถ่ายโอนไฟล์ไบนารีใน [text] ซึ่งจะลดค่าใช้จ่ายในการเข้ารหัสแบบ US-ASCII ก่อนหน้าโดยใช้วิธีการเข้ารหัสแบบ ASCII แบบขยาย 8 บิตส่วนหัวของ yEnc มักจะ (ถ้า แต่ละค่าไบต์ปรากฏขึ้นโดยประมาณด้วยความถี่เดียวกันโดยเฉลี่ย) เพียงเล็กน้อย 1-2% เทียบกับค่าโสหุ้ย 33% –40% สำหรับวิธีการเข้ารหัส 6 บิตเช่น uuencode และ Base64 ... โดยปี 2003 yEnc กลายเป็นมาตรฐานจริง ระบบการเข้ารหัสสำหรับไฟล์ไบนารีบน Usenet "

อย่างไรก็ตาม yEnc เป็นการเข้ารหัสแบบ 8 บิตดังนั้นการจัดเก็บในสตริง JSON จึงมีปัญหาเช่นเดียวกับการจัดเก็บข้อมูลไบนารีดั้งเดิมการทำแบบไร้เดียงสาหมายถึงการขยายตัว 100% ซึ่งแย่กว่า base64


42
เนื่องจากผู้คนจำนวนมากดูเหมือนจะยังคงดูคำถามนี้อยู่ฉันอยากจะพูดถึงว่าฉันไม่คิดว่า yEnc ช่วยได้ที่นี่จริงๆ yEnc เป็นการเข้ารหัสแบบ 8 บิตดังนั้นการจัดเก็บในสตริง JSON จึงมีปัญหาเช่นเดียวกับการจัดเก็บข้อมูลไบนารีดั้งเดิมการทำแบบไร้เดียงสาหมายถึงการขยายตัว 100% ซึ่งแย่กว่า base64
ฮอบส์

ในกรณีที่ใช้การเข้ารหัสเช่น yEnc ที่มีตัวอักษรขนาดใหญ่ที่มีข้อมูล JSON ถือว่าเป็นที่ยอมรับได้escapelessอาจใช้เป็นทางเลือกที่ดีในการให้ค่าใช้จ่ายคงที่ที่ทราบล่วงหน้า
Ivan Kosarev

10

ในขณะที่มันเป็นความจริงที่ base64 มีอัตราการขยายตัวถึง 33% แต่ก็ไม่จำเป็นต้องเป็นความจริงที่ว่าค่าใช้จ่ายในการประมวลผลนั้นสูงกว่านี้: มันขึ้นอยู่กับไลบรารี / ชุดเครื่องมือ JSON ที่คุณใช้ การเข้ารหัสและถอดรหัสเป็นการดำเนินการตรงไปตรงมาอย่างง่ายและยังสามารถปรับการเข้ารหัสอักขระ wrt (เนื่องจาก JSON รองรับเฉพาะ UTF-8/16/32) - อักขระพื้นฐาน 64 ตัวเป็นไบต์เดียวสำหรับรายการสตริง JSON ตัวอย่างเช่นบนแพลตฟอร์ม Java มีไลบรารีที่สามารถทำงานได้ค่อนข้างมีประสิทธิภาพดังนั้นค่าใช้จ่ายส่วนใหญ่จะเกิดจากการขยายขนาด

ฉันเห็นด้วยกับสองคำตอบก่อนหน้านี้:

  • base64 นั้นเป็นมาตรฐานธรรมดาที่ใช้กันทั่วไปดังนั้นจึงไม่น่าจะพบสิ่งที่ดีกว่าที่จะใช้กับ JSON โดยเฉพาะ (base-85 ถูกใช้โดย postscript ฯลฯ แต่ข้อดีอยู่ที่ขอบเขตที่ดีที่สุดเมื่อคุณคิดถึงมัน)
  • การบีบอัดก่อนการเข้ารหัส (และหลังการถอดรหัส) อาจสมเหตุสมผลหลายประการขึ้นอยู่กับข้อมูลที่คุณใช้

10

รูปแบบรอยยิ้ม

มันเร็วมากในการเข้ารหัสถอดรหัสและกะทัดรัด

การเปรียบเทียบความเร็ว (ขึ้นอยู่กับ Java แต่มีความหมาย): https://github.com/eishay/jvm-serializers/wiki/

นอกจากนี้ยังเป็นส่วนขยายของ JSON ที่ให้คุณข้ามการเข้ารหัส base64 สำหรับอาร์เรย์ไบต์

สตริงที่เข้ารหัส Smile สามารถ gzipped เมื่อพื้นที่มีความสำคัญ


3
... และลิงก์นั้นตายไปแล้ว สิ่งนี้ดูเหมือนจะเป็นข้อมูลล่าสุด: github.com/FasterXML/smile-format-specification
Zero3

4

( แก้ไข 7 ปีต่อมา: Google Gears หายไปข้ามคำตอบนี้)


ทีม Google Gears พบปัญหาการขาดข้อมูลไบนารีและพยายามแก้ไขปัญหา:

Blob API

JavaScript มีชนิดข้อมูลในตัวสำหรับสตริงข้อความ แต่ไม่มีอะไรสำหรับข้อมูลไบนารี วัตถุ Blob พยายามแก้ไขข้อ จำกัด นี้

บางทีคุณสามารถสานสิ่งนั้นได้


ดังนั้นสถานะของ blobs ใน Javascript และ json คืออะไร? มันหล่นหรือไม่
chmike

w3.org/TR/FileAPI/#blob-sectionไม่เท่ากับพื้นที่64หากคุณเลื่อนลงคุณจะพบว่ามันเข้ารหัสโดยใช้แผนที่ utf8 (เป็นหนึ่งในตัวเลือกที่แสดงโดยคำตอบของ hobbs) และไม่มีการสนับสนุน json เท่าที่ฉันรู้
Daniele Cruciani

3

เนื่องจากคุณกำลังมองหาความสามารถในการจัดเก็บข้อมูลไบนารีในรูปแบบข้อความและ จำกัด อย่างเคร่งครัดฉันคิดว่าค่าใช้จ่ายของ Base64 นั้นน้อยมากเมื่อเทียบกับความสะดวกสบายที่คุณคาดหวังว่าจะรักษาด้วย JSON หากกังวลเกี่ยวกับกำลังไฟและปริมาณงานคุณอาจต้องพิจารณารูปแบบไฟล์ของคุณใหม่


2

เพียงเพื่อเพิ่มทรัพยากรและความซับซ้อนในการอภิปราย เนื่องจากทำ PUT / POST และ PATCH สำหรับการจัดเก็บทรัพยากรใหม่และปรับเปลี่ยนพวกเขาควรจำไว้ว่าการถ่ายโอนเนื้อหาเป็นการแสดงเนื้อหาที่จัดเก็บไว้อย่างแน่นอนและได้รับจากการดำเนินการ GET

ข้อความที่มีหลายส่วนมักใช้เป็นผู้ช่วยให้รอด แต่ด้วยเหตุผลที่เรียบง่ายและสำหรับงานที่ซับซ้อนมากขึ้นฉันชอบความคิดที่จะให้เนื้อหาโดยรวม มันอธิบายตัวเองและมันง่าย

และใช่ JSON เป็นสิ่งที่ทำให้หมดอำนาจ แต่ในที่สุด JSON ตัวเองเป็น verbose และค่าใช้จ่ายในการทำแผนที่ไปที่ BASE64 เป็นวิธีการเล็ก

การใช้ข้อความที่มีหลายส่วนอย่างถูกต้องมีการแยกวัตถุที่จะส่งใช้เส้นทางคุณสมบัติเป็นชื่อพารามิเตอร์สำหรับการรวมอัตโนมัติหรือจะต้องสร้างโปรโตคอล / รูปแบบอื่นเพื่อแสดงเพย์โหลด

ด้วยความชื่นชอบแนวทาง BSON สิ่งนี้ไม่ได้รับการสนับสนุนอย่างกว้างขวางและง่ายดายเหมือนที่เราต้องการ

โดยพื้นฐานแล้วเราเพิ่งพลาดอะไรบางอย่างที่นี่ แต่การฝังข้อมูลไบนารี่ในฐานะ base64 ได้รับการยอมรับอย่างดีและวิธีการที่จะไปเว้นแต่ว่าคุณได้ระบุความจำเป็นในการถ่ายโอนไบนารีจริง ๆ


1

ฉันขุดอีกเล็กน้อย (ระหว่างการใช้งานbase128 ) และแสดงให้เห็นว่าเมื่อเราส่งตัวอักษรที่รหัส ASCII มีขนาดใหญ่กว่า 128 จากนั้นเบราว์เซอร์ (โครม) ในความเป็นจริงส่งอักขระ TWO (ไบต์) แทนหนึ่ง :(เหตุผลคือ JSON โดย defaul ใช้อักขระ utf8 ซึ่งตัวอักษรที่มีรหัส ascii เหนือ 127 ถูกเขียนโดยสองไบต์สิ่งที่ถูกกล่าวถึงโดยคำตอบchmikeฉันทำการทดสอบด้วยวิธีนี้: พิมพ์ในแถบ URL ของchrome chrome: // net-export / , select "รวม raw bytes ", เริ่มทำการจับ, ส่งคำร้องขอ POST (โดยใช้ตัวอย่างที่ด้านล่าง), หยุดการจับภาพและบันทึกไฟล์ json ด้วยข้อมูลการร้องขอ raw จากนั้นเราจะดูข้างในไฟล์ json นั้น:

  • เราสามารถค้นหาคำขอ base64 ของเราได้โดยการค้นหาสตริง4142434445464748494a4b4c4d4eซึ่งเป็นการเข้ารหัสเลขฐานสิบหกของABCDEFGHIJKLMNและเราจะเห็นสิ่ง"byte_count": 639นั้น
  • เราสามารถค้นหาคำขอข้างต้น 127 ของเราได้โดยค้นหาสตริงC2BCC2BDC380C381C382C383C384C385C386C387C388C389C38AC38Bซึ่งเป็นรหัส request-hex utf8 ของอักขระ¼½ÀÁÂÃÄÅÆÇÈÉÊË(อย่างไรก็ตามรหัสฐานสิบหกของอักขระนี้คือ ASCII c1c2c3c4c5c6c7c8c9cacbcccdce) "byte_count": 703ดังนั้นมันจึงเป็น 64bytes นานกว่า base64 ขอเพราะตัวอักษรที่มีรหัส ASCII เหนือ 127 มีรหัส 2 ไบต์ในคำขอ :(

ดังนั้นในความเป็นจริงเราไม่ได้กำไรจากการส่งตัวอักษรที่มีรหัส> 127 :( สำหรับสายเบส 64 เราไม่สังเกตพฤติกรรมเชิงลบเช่นนั้น (อาจเป็นฐานที่ 85 - ฉันไม่ตรวจสอบ) - อย่างไรก็ตามอาจเป็นวิธีแก้ปัญหานี้ การส่งข้อมูลในส่วนไบนารีของ POST multipart / form-data ที่อธิบายไว้ในคำตอบ answerlex (อย่างไรก็ตามโดยทั่วไปแล้วในกรณีนี้เราไม่จำเป็นต้องใช้การเข้ารหัสพื้นฐานใด ๆ เลย ... )

ทางเลือกอื่นอาจอาศัยการแม็พสองส่วนข้อมูลไบต์เป็นอักขระ utf8 ที่ถูกต้องหนึ่งตัวด้วยรหัสโดยใช้บางอย่างเช่นbase65280 / base65kแต่อาจจะมีประสิทธิภาพน้อยกว่า base64 เนื่องจากข้อกำหนด utf8 ...


0

ชนิดข้อมูลกังวลจริงๆ ฉันได้ทดสอบสถานการณ์ต่าง ๆ เกี่ยวกับการส่งเพย์โหลดจากทรัพยากรที่สงบ สำหรับการเข้ารหัสฉันใช้ Base64 (Apache) และการบีบอัด GZIP (java.utils.zip. *) เพย์โหลดประกอบด้วยข้อมูลเกี่ยวกับภาพยนตร์รูปภาพและไฟล์เสียง ฉันบีบอัดและเข้ารหัสไฟล์ภาพและเสียงซึ่งทำให้ประสิทธิภาพลดลงอย่างมาก การเข้ารหัสก่อนการบีบอัดเปิดออกได้ดี เนื้อหารูปภาพและเสียงถูกส่งเป็นการเข้ารหัสและบีบอัดไบต์ []


0

อ้างอิง: http://snia.org/sites/default/files/Multi-part%20MIME%20Extension%20v1.0g.pdf

มันอธิบายวิธีการถ่ายโอนข้อมูลไบนารีระหว่างไคลเอนต์ CDMI และเซิร์ฟเวอร์โดยใช้การดำเนินงาน 'ประเภทเนื้อหา CDMI' โดยไม่ต้องแปลงฐาน 64 ของข้อมูลไบนารี

หากคุณสามารถใช้การดำเนินการ 'ประเภทเนื้อหาที่ไม่ใช่ CDMI' มันเหมาะที่จะถ่ายโอนข้อมูลไปยัง / จากวัตถุ ข้อมูลเมตาสามารถเพิ่ม / เรียกคืนไปยัง / จากวัตถุในภายหลังเป็นการดำเนินการ 'ประเภทเนื้อหา CDMI' ที่ตามมา


-1

โซลูชันของฉันในตอนนี้ XHR2 กำลังใช้ ArrayBuffer ArrayBuffer เป็นเลขฐานสองประกอบด้วยมัลติเนื้อหาวิดีโอเสียงกราฟิกข้อความและอื่น ๆ ที่มีเนื้อหาหลายประเภท ทั้งหมดใน One Response

ในเบราว์เซอร์ที่ทันสมัยมี DataView, StringView และ Blob สำหรับส่วนประกอบต่าง ๆ ดูเพิ่มเติมที่: http://rolfrost.de/video.htmlสำหรับรายละเอียดเพิ่มเติม


คุณจะทำให้ข้อมูลของคุณเติบโตขึ้น + 100% โดยการเรียงลำดับอาร์เรย์เป็นจำนวนมาก
Sharcoux

@Sharcoux wot ??
Mihail Malostanidis

การทำให้เป็นลำดับของอาร์เรย์ไบต์ใน JSON นั้นคล้ายกับ: [16, 2, 38, 89]ซึ่งไม่มีประสิทธิภาพมาก
Sharcoux
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.