کتابخانه‌ی استاندارد · کدگذاری و داده

مسج‌پک encoding/msgpack

قالب دودویی و فشرده‌ی MessagePack برای مقدارهای پویا.

واردسازی کدگذاری.مسج‌پک

MessagePack همان داده‌ی جیسون را به شکل دودویی و کوتاه‌تر نگه می‌دارد و خواندنش سریع‌تر است؛ برای پیام‌های میان سرویس‌ها، مدخل‌های حافظه‌ی نهان و RPC مناسب است. این بسته یک مقدار را با سریال سازی به یک فشرده سازی.بافر بایت تبدیل می‌کند و با واسریال سازی (یا واسریال سازی بایت‌ها برای حافظه‌ی خام) آن را برمی‌گرداند. خطاها در یک خطای کدگذاری می‌رسند.

وقتی هر دو طرف برنامه‌اند و اندازه یا سرعت مهم است، آن را به جیسون ترجیح دهید؛ وقتی آدم‌ها داده را می‌خوانند یا مرورگر آن را مصرف می‌کند، جیسون را نگه دارید. برای چینش دودویی ثابتی که خودتان تعریف کرده‌اید، مثل سرآیند یک پرونده، فیلدها را مستقیم با دودویی بنویسید؛ و برای طرح‌واره‌هایی که میان زبان‌ها مشترک‌اند، پروتوباف.

مقدارها چطور نوشته می‌شوند

مقدارMessagePack
تهی، منطقیnil، true/false
صحیحکوچک‌ترین قالب عدد صحیحی که جا شود، از یک تا ۸ بایت
اعشاریهمیشه float64 (۹ بایت)؛ float32 خوانده می‌شود ولی هرگز نوشته نمی‌شود
رشتهبسته به طول، fixstr، str8، str16 یا str32
آرایه، شیءfixarray/array16/array32 و fixmap/map16/map32 با کلیدهای رشته‌ای

اشتباه‌های رایج

  • نوع‌های bin و ext پشتیبانی نمی‌شوند. داده‌ای از کتابخانه‌ای دیگر که بایت‌ها را به شکل bin یا مهر زمانی را به شکل ext نگه دارد، با نوع سفارشی شکست می‌خورد. رشته‌ها در نخستین بایت صفر تمام می‌شوند، پس داده‌ی دودویی را در رشته هم نمی‌شود فرستاد؛ اول آن را Base64 کنید.
  • کلیدهای نگاشت باید رشته باشند. نگاشتی با کلیدهای عددی، که برخی کتابخانه‌های دیگر می‌نویسند، طوری خوانده می‌شود که همه‌ی کلیدها "" می‌شوند و مدخل‌ها روی هم می‌نشینند.
  • بایت‌های پس از مقدار نادیده گرفته می‌شوند. واسریال سازی یک مقدار می‌خواند و نمی‌گوید بعدش چه آمده یا چند بایت مصرف کرده، پس نمی‌توانید چند پیام را از یک بافر بخوانید. هر پیام را خودتان قاب‌بندی کنید، مثلاً با طولی ۴ بایتی در جلوی آن.
  • میان فراخوانی‌ها خطا را از نو بسازید. اگر خطای کدگذاریای که می‌دهید از قبل خطا داشته باشد، واسریال سازی بی‌درنگ تهی برمی‌گرداند.
  • عددهای بزرگ‌تر از i64 (یک uint64 بیش از 9223372036854775807) دور می‌زنند و منفی می‌شوند.

راهنما: چقدر کوچک‌تر است؟

مسج‌پک نقل‌قول‌ها، دونقطه‌ها و ویرگول‌های جیسون را کنار می‌گذارد و عددها و طول‌ها را با کمترین بایت ممکن نگه می‌دارد. برای رکوردهایی با کلیدهای کوتاه و عددهای کوچک، معمولاً به نصف یا دوسوم جیسون فشرده می‌رسد. جیسون را یک بار به یک مقدار کدگشایی کنید و سریال سازی آن را به شکل مسج‌پک می‌نویسد.

encoding-msgpack-guide-size.salam
واردسازی کدگذاری.مسج‌پک
واردسازی کدگذاری.جیسون
واردسازی کدگذاری.مقدار
واردسازی کدگذاری.خطای کدگذاری
واردسازی فشرده سازی

تابع ریشه:
    متن := `[{"id": 1, "name": "tea", "price": 120, "stock": true},
 {"id": 2, "name": "coffee", "price": 90, "stock": true},
 {"id": 3, "name": "cocoa", "price": 75, "stock": false}]`
    ناپایا خطا := خطای کدگذاری.بدون خطا()
    ردیف‌ها := جیسون.کدگشایی(متن، خطا)

    فشرده := جیسون.کدگذاری پیش فرض(ردیف‌ها)
    بسته‌بندی := مسج‌پک.سریال سازی(ردیف‌ها)
    سرچاپ "بایت‌های جیسون:   "، فشرده.طول()
    سرچاپ "بایت‌های مسج‌پک:  "، فشرده سازی.طول بافر(بسته‌بندی)

    برگشتی := مسج‌پک.واسریال سازی(بسته‌بندی، خطا)
    سرچاپ "همان داده:"، مقدار.یکسان است(ردیف‌ها، برگشتی)، "خطا:"، خطای کدگذاری.خطا است(خطا)
پایان
خروجیبایت‌های جیسون: 169 بایت‌های مسج‌پک: 90 همان داده: true خطا: false

کلیدها هنوز در هر رکورد کامل نوشته می‌شوند، پس نام‌های بلند کلید همان‌قدر هزینه دارند که در جیسون. اگر اندازه از این هم مهم‌تر است، بافر را با بسته‌ی فشرده سازی هم فشرده کنید.

راهنما: بایت‌ها چه شکلی‌اند

هر مقدار با یک بایت نوع شروع می‌شود. عددهای صحیح کوچک از ۰ تا ۱۲۷ یک بایت‌اند و بزرگ‌ترها نشانه‌ای مثل cc (یک بایت پس از آن) یا ce (چهار بایت پس از آن) می‌گیرند. رشته‌ها، آرایه‌ها و نگاشت‌های کوتاه طولشان را در بایت اول دارند: a2 رشته‌ای ۲ بایتی است، 92 آرایه‌ای با ۲ عضو و 81 نگاشتی با یک جفت.

encoding-msgpack-guide-bytes.salam
واردسازی کدگذاری.مسج‌پک
واردسازی کدگذاری.مقدار
واردسازی فشرده سازی

تابع شانزدهی(م: مقدار.مقدار): رشته:
    رقم‌ها := "0123456789abcdef"
    ناپایا ب := مسج‌پک.سریال سازی(م)
    ناپایا خروجی := ""
    تکرار فشرده سازی.طول بافر(ب) در ای:
        ایکس := فشرده سازی.دریافت بایت(ب، ای)
        اگر ای > ۰:
            خروجی = خروجی + " "
        پایان
        خروجی = خروجی + رقم‌ها.زیررشته(ایکس / ۱۶، ۱) + رقم‌ها.زیررشته(ایکس % ۱۶، ۱)
    پایان
    فشرده سازی.آزادسازی بافر(ب)
    برگشت خروجی
پایان

تابع ریشه:
    سرچاپ "5       "، شانزدهی(مقدار.مقدار صحیح(۵))
    سرچاپ "-1      "، شانزدهی(مقدار.مقدار صحیح(-۱))
    سرچاپ "200     "، شانزدهی(مقدار.مقدار صحیح(۲۰۰))
    سرچاپ "70000   "، شانزدهی(مقدار.مقدار صحیح(۷۰۰۰۰))
    سرچاپ "true    "، شانزدهی(مقدار.مقدار منطقی(درست))
    سرچاپ "null    "، شانزدهی(مقدار.مقدار تهی())
    سرچاپ "1.5     "، شانزدهی(مقدار.مقدار اعشاری(۱.۵))
    سرچاپ "\"hi\"    "، شانزدهی(مقدار.مقدار رشته("hi"))

    ناپایا آرایه := مقدار.آرایه جدید()
    مقدار.افزودن به آرایه(آرایه، مقدار.مقدار صحیح(۱))
    مقدار.افزودن به آرایه(آرایه، مقدار.مقدار صحیح(۲))
    سرچاپ "[1, 2]  "، شانزدهی(آرایه)

    ناپایا شیء := مقدار.شیء جدید()
    مقدار.تنظیم کلید(شیء، "a"، مقدار.مقدار صحیح(۱))
    سرچاپ "{\"a\": 1}"، شانزدهی(شیء)
پایان
خروجی5 05 -1 ff 200 cc c8 70000 ce 00 01 11 70 true c3 null c0 1.5 cb 3f f8 00 00 00 00 00 00 "hi" a2 68 69 [1, 2] 92 01 02 {"a": 1} 81 a1 61 01

برنامه بافر را بایت به بایت با فشرده سازی.دریافت بایت می‌خواند. تبدیل بافر به رشته در اینجا کار نمی‌کرد: 70000 یک بایت صفر دارد و رشته در نخستین صفر تمام می‌شود. داده‌ی مسج‌پک را در بافر بایت خودش نگه دارید، یا هر جا متن لازم دارید از بافر به پایه۶۴ استفاده کنید.

راهنما: ساختارها در حافظه‌ی نهان

حافظه‌ی نهانی مثل ردیس بایت نگه می‌دارد و بایت‌های مسج‌پک زودتر از جیسون خوانده می‌شوند. برای یک ساختار، در رفت و برگشت از جیسون بگذرید: جیسون.سریال سازی و جیسون.کدگشایی مقداری برای بسته‌بندی می‌دهند و جیسون.واسریال سازی ساختار را از مقدار بازشده پر می‌کند. اینجا یک نگاشت جای حافظه‌ی نهان را گرفته است.

encoding-msgpack-guide-cache.salam
واردسازی کدگذاری.مسج‌پک
واردسازی کدگذاری.جیسون
واردسازی کدگذاری.خطای کدگذاری
واردسازی فشرده سازی

ساختار نشست:
    @جیسون "user"
    همگانی کاربر: رشته = ""
    @جیسون "role"
    همگانی نقش: رشته = ""
    @جیسون "visits"
    همگانی بازدید: صحیح = ۰
پایان

تابع ذخیره(نهان &: نگاشت<رشته، فشرده سازی.بافر بایت>، کلید: رشته، ن: نشست):
    ناپایا خطا := خطای کدگذاری.بدون خطا()
    م := جیسون.کدگشایی(جیسون.سریال سازی(ن)، خطا)
    نهان.درج(کلید، مسج‌پک.سریال سازی(م))
پایان

تابع بارگذاری(نهان: نگاشت<رشته، فشرده سازی.بافر بایت>، کلید: رشته، خروجی &: نشست): منطقی:
    اگر وارونه نهان.دارد(کلید):
        برگشت نادرست
    پایان
    ناپایا خطا := خطای کدگذاری.بدون خطا()
    م := مسج‌پک.واسریال سازی(نهان.بگیر(کلید)، خطا)
    اگر خطای کدگذاری.خطا است(خطا):
        برگشت نادرست
    پایان
    برگشت جیسون.واسریال سازی(جیسون.کدگذاری پیش فرض(م)، خروجی، خطا)
پایان

تابع ریشه:
    ناپایا نهان := نگاشت {} برگردان نگاشت<رشته، فشرده سازی.بافر بایت>
    ذخیره(نهان، "session:9f2"، نشست { کاربر = "sara"، نقش = "admin"، بازدید = ۱۲ })

    ناپایا ن := نشست {}
    اگر بارگذاری(نهان، "session:9f2"، ن):
        سرچاپ "پیدا شد:"، ن.کاربر، ن.نقش، ن.بازدید
    پایان
    سرچاپ "کلید نبوده بارگذاری شد:"، بارگذاری(نهان، "session:000"، ن)
پایان
خروجیپیدا شد: sara admin 12 کلید نبوده بارگذاری شد: false

برای یک حافظه‌ی نهان واقعی، ب.data و ب.len را به شکل مقدار دودویی به کتابخانه‌ی کارخواه بدهید و آنچه برمی‌گردد را با واسریال سازی بایت‌ها کدگشایی کنید.

راهنما: بافر خراب، بریده یا بیگانه

خواندن از شبکه ممکن است نیمه‌کاره بماند و برنامه‌های دیگر ممکن است بخش‌هایی از MessagePack را به کار ببرند که این بسته نمی‌خواند. هم واسریال سازی و هم واسریال سازی بایت‌ها بافری را که وسط یک مقدار تمام شود با نوع اتمام ناگهانی گزارش می‌کنند، پس می‌توانید «منتظر بایت‌های بیشتر بمان» را از داده‌ای که به‌کل نادرست است جدا کنید.

encoding-msgpack-guide-errors.salam
واردسازی کدگذاری.مسج‌پک
واردسازی کدگذاری.مقدار
واردسازی کدگذاری.خطای کدگذاری
واردسازی فشرده سازی

تابع ریشه:
    ناپایا م := مقدار.شیء جدید()
    مقدار.تنظیم کلید(م، "name"، مقدار.مقدار رشته("salam"))
    ب := مسج‌پک.سریال سازی(م)

    ناپایا خطا := خطای کدگذاری.بدون خطا()
    کامل := مسج‌پک.واسریال سازی بایت‌ها(ب.داده، ب.طول، خطا)
    سرچاپ "کل بافر:"، خطای کدگذاری.خطا است(خطا)، مقدار.به رشته(مقدار.مقدار کلید(کامل، "name"))

    ناپایا بریده := خطای کدگذاری.بدون خطا()
    _ := مسج‌پک.واسریال سازی بایت‌ها(ب.داده، ب.طول - ۳، بریده)
    سرچاپ "بریده:"، خطای کدگذاری.خطا است(بریده)، بریده.نوع == خطای کدگذاری.نوع اتمام ناگهانی، بریده.پیام

    ناپایا لکه := فشرده سازی.بافر بایت جدید()
    فشرده سازی.افزودن بایت(لکه، 0xc4)
    فشرده سازی.افزودن بایت(لکه، ۲)
    فشرده سازی.افزودن بایت(لکه، 0xca)
    فشرده سازی.افزودن بایت(لکه، 0xfe)
    ناپایا دودویی := خطای کدگذاری.بدون خطا()
    _ := مسج‌پک.واسریال سازی(لکه، دودویی)
    سرچاپ "bin از کتابخانه‌ای دیگر:"، دودویی.نوع == خطای کدگذاری.نوع سفارشی، دودویی.پیام

    ناپایا دوتایی := فشرده سازی.کپی بافر(ب)
    فشرده سازی.افزودن بایت(دوتایی، 0x2a)
    ناپایا اضافه := خطای کدگذاری.بدون خطا()
    نخست := مسج‌پک.واسریال سازی(دوتایی، اضافه)
    سرچاپ "یک بایت اضافه پس از مقدار:"، خطای کدگذاری.خطا است(اضافه)، مقدار.طول شیء(نخست)، "کلید خوانده شد"
پایان
خروجیکل بافر: false salam بریده: true true unexpected end of input bin از کتابخانه‌ای دیگر: true unsupported msgpack tag (ext/bin types are not supported) یک بایت اضافه پس از مقدار: false 1 کلید خوانده شد

حالت سوم یک مقدار bin با بایت نوع c4 است، همان چیزی که کتابخانه‌هایی می‌نویسند که بایت را از رشته جدا نگه می‌دارند؛ با نوع سفارشی شکست می‌خورد. وقتی فرستنده باید با سلام حرف بزند، از او بخواهید رشته بفرستد یا بایت‌ها را Base64 کند. حالت آخر نشان می‌دهد یک بایت سرگردان پس از مقدار کامل دیده نمی‌شود؛ برای همین جریانی از پیام‌ها قاب‌بندی خودش را لازم دارد.

گونه‌ها

گزینه‌های مسج‌پک MsgpackOptions

ساختار گزینه‌های مسج‌پک
گزینه‌های سریال‌سازی.
نامانگلیسیگونهتوضیح
قالب کوتاه رشتهuse_str8منطقی = درستبرای رشته‌های ۳۲ تا ۲۵۵ بایتی از قالب str8 استفاده شود؛ پیش‌فرض درست. برای خواننده‌های خیلی قدیمی که str8 را نمی‌شناسند نادرستش کنید؛ آن‌وقت این رشته‌ها به شکل str16 نوشته می‌شوند.
encoding-msgpack-Marshal.salam
واردسازی کدگذاری.مسج‌پک
واردسازی کدگذاری.مقدار
واردسازی کدگذاری.خطای کدگذاری
واردسازی کدگذاری
واردسازی فشرده سازی

تابع ریشه:
    ناپایا م := مقدار.شیء جدید()
    مقدار.تنظیم کلید(م، "id"، مقدار.مقدار صحیح(۷))
    مقدار.تنظیم کلید(م، "ok"، مقدار.مقدار منطقی(درست))
    ب := مسج‌پک.سریال سازی(م)
    سرچاپ فشرده سازی.طول بافر(ب)، فشرده سازی.بافر به پایه۶۴(ب)
    ناپایا خ := خطای کدگذاری.بدون خطا()
    ب۲ := مسج‌پک.واسریال سازی(ب، خ)
    سرچاپ خطای کدگذاری.خطا است(خ)، مقدار.یکسان است(م، ب۲)، مقدار.به صحیح(مقدار.مقدار کلید(ب۲، "id"))
    ب۳ := مسج‌پک.واسریال سازی بایت‌ها(ب.داده، ب.طول، خ)
    سرچاپ مقدار.یکسان است(م، ب۳)
    گ := مسج‌پک.گزینه‌های مسج‌پک {}
    سرچاپ فشرده سازی.طول بافر(مسج‌پک.سریال سازی سفارشی(م، گ))
    سرچاپ کدگذاری.کدگذاری شانزده(فشرده سازی.بافر به رشته(مسج‌پک.سریال سازی(مقدار.مقدار صحیح(۵))))
پایان
خروجی9 gqJpZAeib2vD false true 7 true 9 05

تابع‌ها

سریال سازی سفارشی MarshalWith

تابع سریال سازی سفارشی(v: value.Value، opts: گزینه‌های مسج‌پک): compress.ByteBuf
مقدار را با گزینه‌های داده‌شده به بایت‌های مسج‌پک تبدیل می‌کند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: encoding-msgpack-Marshal.salam

سریال سازی Marshal

تابع سریال سازی(v: value.Value): compress.ByteBuf
مقدار را به بایت‌های مسج‌پک تبدیل می‌کند. وقتی کارتان تمام شد، بافر را با فشرده سازی.آزادسازی بافر آزاد کنید.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: encoding-msgpack-Marshal.salam

واسریال سازی بایت‌ها UnmarshalBytes

تابع واسریال سازی بایت‌ها(p: تهی*، n: صحیح، err &: encerr.EncodingError): value.Value
یک مقدار مسج‌پک را از n بایت در نشانی p می‌خواند، برای داده‌ای که در بافر بایت نیست، مثل پاسخ یک کارخواه حافظه‌ی نهان. بایت‌های پس از مقدار نادیده گرفته می‌شوند.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: encoding-msgpack-Marshal.salam

واسریال سازی Unmarshal

تابع واسریال سازی(b: compress.ByteBuf، err &: encerr.EncodingError): value.Value
بافر مسج‌پک را به مقدار تبدیل می‌کند؛ اگر داده بریده باشد یا bin یا ext داشته باشد، err پر می‌شود. هر بار یک بدون خطا() تازه بدهید.

نمونه‌ی این مورد همراه با موارد بالاتر آمده است: encoding-msgpack-Marshal.salam