std.encoding.json
API summary (generated from the Beans source by npm run coverage): 10 package functions · 7 types · 8 static methods · 15 instance methods · 7 public fields · 13 enum variants.
std.encoding.json JSON পড়ে আর লেখে। DOM-ধাঁচের একটা Value পেতে parse,
ইনপুটকে struct tree-তে নিতে decode<T>, আর struct tree-কে JSON string বানাতে
encode<T> ব্যবহার করুন। এর পেছনে আছে yyjson (MIT)। সোর্স হলো
stdlib/std/encoding/json/json.b।
import std.encoding.jsonএকটা Value পুরো document-এর একটা shared reference ধরে রাখে। Child value-গুলো
document-টাকে বাঁচিয়ে রাখে, তাই parse থেকে টেনে বের করা কোনো value যতক্ষণ ধরে
রাখা হয় ততক্ষণ valid থাকে। একটা Value কপি করা সস্তা। Parsing ডিফল্টে কড়া RFC 8259।
--runtime freestanding দিয়ে বানানো একটা build std.encoding মানে না; এই
প্যাকেজগুলোর hosted runtime লাগে।
Typed struct
“Typed struct” সেকশনdecode<T> কম্পাইল টাইমে concrete mapping-টা বানিয়ে ফেলে। এর native fast path কোনো
public Value wrapper বানায় না আর কোনো runtime reflection metadata স্ক্যান করে না।
import std.encoding.json
struct Storage { @json.name(value: "type") pub storage_type: string pub capacity_tb: float}
struct Product { pub sku: string pub tags: List<string> pub storage: Option<Storage>}
fn read_product(text: string) -> Result<Product> { return json.decode(text)}Typed entry point-গুলো হলো:
pub fn decode<T>(text: string) -> Result<T>pub fn decode_bytes<T>(data: Bytes) -> Result<T>pub fn decode_bytes_in_place<T>(move data: Bytes) -> Result<T>pub fn decode_with_options<T>(text: string, options: DecodeOptions) -> Result<T>pub fn encode<T>(value: T) -> Result<string>pub fn encode_pretty<T>(value: T, indent: string) -> Result<string>দুই দিকেই struct root বা List<Struct> root চলে। Field-এ boolean, নানা প্রস্থের
integer, f32, float, string, nested struct, এক স্তরের list, বা এক স্তরের option
থাকতে পারে। Option-এর ভেতরে supported scalar, struct, বা list থাকতে পারে। Nested
list আর nested option চলে না। @json.name, @json.alias, @json.ignore,
@json.naming, আর @json.allow_unknown mapping নিয়ন্ত্রণ করে। Encoding primary
mapped নাম ব্যবহার করে; alias শুধু input-এর জন্য। Ignored field output-এ থাকে না।
ভুল root, recursive schema, ডুপ্লিকেট mapped নাম, class, enum, map, fixed array,
Bytes, decimal, unit, আর generic struct কম্পাইল টাইমেই ফেল করে। @json.bytes
contract রিজার্ভ করা আছে, তবে typed Bytes support এখনো বানানো হয়নি।
Decode করার সময় ignored field-এর default থাকতে হবে, আর একই schema-তে nested
struct বা list field রাখা যাবে না। Encoding-এ এই সীমা নেই।
ডিফল্টে, না-থাকা required field, অচেনা key, ডুপ্লিকেট key, ভুল kind, আর numeric
overflow — সবই error। একটা না-থাকা Option<T> হয়ে যায় none; একটা option-এর
জন্য JSON null মানা হয়।
decode_bytes_in_place(move data) ব্যবহার করুন যখন ইনপুট বাফারটা আর লাগবে না। এটা
yyjson-কে সেই allocation-এ জায়গামতোই parse করতে দেয়, তাই একটা বড় payload-এর জন্য
আর দ্বিতীয় কোনো parse বাফার লাগে না। ফেরত পাওয়া string আর collection-গুলো এখনো
নিজেদের data-র মালিক থাকে আর অস্থায়ী parse tree চলে যাওয়ার পরেও valid থাকে। সাধারণ
decode আর decode_bytes রূপ কোনো bridge staging ছাড়াই তাদের ইনপুট borrow করে,
কিন্তু সেটা খেয়ে ফেলে না।
fn read_product_file(path: string) -> Result<Product> { let input: Bytes = fs.read_bytes(path)? return json.decode_bytes_in_place(move input)}Typed mapping type
“Typed mapping type” সেকশনNaming একটা struct-এর প্রতিটা annotation-ছাড়া field-এর নাম বদলে দেয়:
pub enum Namingexactcamel_casesnake_caseBytesFormat typed Bytes সাপোর্টের দুইটা রূপ রিজার্ভ করে রাখে। Bytes decoding
নিজে এই রিলিজে বানানো হয়নি।
pub enum BytesFormatbase64arrayDecodeOptions typed-decoder-এর parser flag আর nesting limit বহন করে:
pub class DecodeOptionspub parse: Optionspub max_depth: intডিফল্ট হলো কড়া parsing আর সর্বোচ্চ depth 128।
encode compact JSON লেখে। encode_pretty-র indent হুবহু দুই বা চারটা space
হতে হয়। Option.none JSON null হয়; NaN আর infinity error। Print করাটা স্পষ্ট:
import std.ioimport std.encoding.json
struct User { pub id: u64 pub name: string}
fn main() { let user: User = User { id: 7, name: "Ada" } io.println(json.encode(user).expect("encode user"))}Kind
“Kind” সেকশনKind বলে দেয় একটা value কী ধরে আছে।
pub enum Kindnullbooleanintegerunsigned_integerfloatingtextarrayobjectসংখ্যা তাদের parse করা kind রাখে: signed integer, unsigned integer, আর
floating-point value আলাদা থাকে, f64-তে গুলিয়ে যায় না। i64 আর u64 দুটোর
জন্যই বড্ড বড় একটা integer floating হিসেবে parse হয়।
Options
“Options” সেকশনOptions তিনটা এক্সটেনশন চালু করার সুযোগ দেয়। প্রতিটা field ডিফল্টে বন্ধ, তাই
একটা চালু না করা পর্যন্ত parser কড়া RFC 8259।
pub class Optionsallow_comments: bool = falseallow_trailing_commas: bool = falseallow_inf_nan: bool = falseএই তিন flag হলো JSON5-এর একটা ছোট অংশ, ইচ্ছে করেই পুরো JSON5 না: unquoted key আর single quote এখনো বাতিল হয়।
Entry
“Entry” সেকশনএকটা object থেকে একটা key/value জোড়া, যেমনটা entries() ফেরত দেয়।
pub struct Entrypub key: stringpub value: Valueএকটা value পড়া
“একটা value পড়া” সেকশনpub fn kind() -> Kindpub fn is_null() -> boolpub fn to_bool() -> Result<bool>pub fn to_int() -> Result<int>pub fn to_uint() -> Result<u64>pub fn to_float() -> Result<float>pub fn number() -> Result<float>pub fn to_string() -> Result<string>pub fn len() -> Result<int>pub fn at(index: int) -> Result<Value>pub fn elements() -> Result<List<Value>>pub fn get(key: string) -> Option<Value>pub fn entries() -> Result<List<Entry>>- value-টা ভুল kind-এর হলে
to_*reader-গুলোtypekind দিয়ে ফেল করে।to_intএকটা unsigned integer মানে যদি সেটাi64-তে আঁটে;to_uintএকটা signed integer মানে যদি সেটা negative না হয়;numberযেকোনো numeric kind মানে আর সেটাকে float হিসেবে ফেরত দেয়। - index সীমার বাইরে হলে
atrangekind দিয়ে ফেল করে। getনা-থাকা key-র জন্যnoneফেরত দেয়, অথবা value-টা object না হলে। একটা না-থাকা field কোনো error না। ডুপ্লিকেট key থাকলে এটা প্রথমটা ফেরত দেয়;entries()document-এর ক্রম অনুযায়ী সবগুলো জানায়।
একটা field পড়ে, আর না-থাকাটাকে error না ভেবে অনুপস্থিত হিসেবে ধরা যায়:
import std.ioimport std.encoding.json
fn main() { let doc: json.Value = json.parse("\{\"name\": \"beans\", \"stars\": 3\}").expect("parse")
match doc.get("name") { some(value) => io.println(value.to_string().expect("name is text")), none => io.println("no name"), } match doc.get("website") { some(value) => io.println(value.to_string().expect("website is text")), none => io.println("no website field"), }}একটা value বানানো
“একটা value বানানো” সেকশনএই constructor দিয়ে বানানো value mutable document-এ থাকে। push আর add তাদের
argument-কে deep-copy করে, তাই একটা value দুইবার insert করা যায় বা অবাধে শেয়ার করা যায়।
pub static fn null() -> Valuepub static fn from_bool(value: bool) -> Valuepub static fn from_int(value: int) -> Valuepub static fn from_uint(value: u64) -> Valuepub static fn from_float(value: float) -> Valuepub static fn from_string(value: string) -> Valuepub static fn array() -> Valuepub static fn object() -> Valuepub fn push(item: Value) -> Result<bool>pub fn add(key: string, item: Value) -> Result<bool>parse থেকে আসা value-গুলো read-only: এদের উপর push বা add কল করলে immutable
kind-এর একটা err ফেরত আসে। (immutable একটা error kind, Kind-এর কোনো variant
না।) mutate করার দরকার হলে নতুন value তৈরি করতে হয়।
import std.ioimport std.encoding.json
fn main() { let obj: json.Value = json.Value.object() obj.add("name", json.Value.from_string("beans")).expect("add name") obj.add("stars", json.Value.from_int(3)).expect("add stars")
let tags: json.Value = json.Value.array() tags.push(json.Value.from_string("small")).expect("push tag") obj.add("tags", tags).expect("add tags")
io.println(json.stringify(obj).expect("stringify"))}Parse আর print করা
“Parse আর print করা” সেকশনpub fn parse(text: string) -> Result<Value>pub fn parse_bytes(data: Bytes) -> Result<Value>pub fn parse_with_options(text: string, options: Options) -> Result<Value>pub fn parse_bytes_with_options(data: Bytes, options: Options) -> Result<Value>pub fn stringify(value: Value) -> Result<string>pub fn stringify_pretty(value: Value, indent: string) -> Result<string>- পুরো ইনপুটটা এক document হতে হবে; শেষে বাড়তি কিছু থাকলে সেটা error।
stringifycompact JSON লেখে। কোনো NaN বা infinite সংখ্যা থাকলে result-এর kind হয়invalid।stringify_prettyindent করে;indentstring-টা হুবহু দুই স্পেস (" ") বা চার স্পেস (" ") হতে হবে, নয়তোinvalidkind পাওয়া যায়।- Parse error ফেরত আসে
invalid,eof, বাmemorykind নিয়ে, আর message-এ থাকে ঠিক কোন byte position-এ সমস্যাটা পাওয়া গেল।
crash না করে একটা parse error সামলানো যায়:
import std.ioimport std.encoding.json
fn main() { match json.parse("\{ not valid ]") { ok(value) => io.println("parsed a document with {value.len().expect("len")} entries"), err(problem) => io.println("bad JSON ({problem.kind}): {problem.msg}"), }}comment আর trailing comma মানতে চাইলে Options পাঠাতে হয়:
import std.encoding.json
fn main() { var options: json.Options = new json.Options() options.allow_comments = true options.allow_trailing_commas = true let doc: json.Value = json.parse_with_options("[1, 2, 3,] // ok", options).expect("parse")}