একটি JSON অবজেক্ট হলো, অন্য ভাষার পরিভাষায় বললে, একটি "hash", "map" বা "dictionary"।
JSON একটি অবজেক্ট-কে এভাবে সংজ্ঞায়িত করে:
একটি অবজেক্ট হলো নাম/মান জোড়ার একটি অবিন্যস্ত সেট। একটি অবজেক্ট
{বাম ব্রেস দিয়ে শুরু হয় এবং}ডান ব্রেস দিয়ে শেষ হয়। প্রতিটি নাম-এর পরে:কোলন থাকে এবং নাম/মান জোড়াগুলো,কমা দিয়ে আলাদা করা হয়।
নাম অবশ্যই একটি স্ট্রিং হতে হবে। নাম-এর আরেকটি প্রতিশব্দ হলো কী (key)।
মান যেকোনো JSON টাইপের হতে পারে। একই অবজেক্টের ভিন্ন ভিন্ন মান ভিন্ন ভিন্ন টাইপের হতে পারে, যেমন এই উদাহরণে।
{
"name": "Jane",
"age": 42,
"pets": ["cat", "fish"],
"address": {"street": "123 Main St", "city": "Springfield"}
}
মনে রাখবেন, শেষ কী (key)-ভ্যালু জোড়ার পরে কোনো কমা থাকা যাবে না।
নাম/মান জোড়াগুলো একত্র করতে ব্রেস ব্যবহার করুন। নামগুলো স্ট্রিং হতে হলেও, নামগুলো আইডেন্টিফায়ার-সদৃশ (আলফানিউমেরিক ক্যারেক্টার আর আন্ডারস্কোর দিয়ে গঠিত, এবং কোনো ডিজিট দিয়ে শুরু হয়নি) হলে সেগুলো কোট করার দরকার নেই।
{name: "Jane", age: 42}
আইডেন্টিফায়ার-সদৃশ নয় এমন কী (key) ব্যবহার করাও বৈধ। শুধু সেগুলো কোট করে দিন।
{"first name": "Jane", "last name": "Lopez", age: 42}
নাম যদি কোনো এক্সপ্রেশনের ফলাফল হয়, তাহলে এক্সপ্রেশনটি অবশ্যই বন্ধনীর ভিতরে থাকতে হবে।
$ echo "Jane" | jq -Rc '{.: 42}'
# verbose error message ...
$ echo "Jane" | jq -Rc '{(.): 42}'
{"Jane":42}
ডট নোটেশন দিয়ে অবজেক্ট থেকে মান বের করা হয়।
{name: "Jane", age: 42} | .age # => 42
কোনো কী (key)-কে আইডেন্টিফায়ার হিসেবে উল্লেখ করতে না পারলে ব্র্যাকেট নোটেশন ব্যবহার করুন।
"name" as $key | {name: "Jane", age: 42} | .$key # => error
"name" as $key | {name: "Jane", age: 42} | .[$key] # => "Jane"
একটি অ্যারেতে নতুন একটি কী (key)-ভ্যালু জোড়া যোগ করতে, বা বিদ্যমান কোনো কী (key)-এর মান হালনাগাদ করতে, বাম দিকে একটি ইনডেক্স এক্সপ্রেশন দিয়ে = অ্যাসাইনমেন্ট অপারেটর ব্যবহার করুন।
{name: "Jane", age: 42} | .sport = "tennis" | .age = 21
# => {
# "name": "Jane",
# "age": 21,
# "sport": "tennis"
# }
+ অপারেটর অবজেক্টগুলোকে মার্জ করবে।
{Richard: 54} + {Jane: 42}
# => {
# "Richard": 54,
# "Jane": 42
# }
একটি কী (key) মুছে ফেলতে del ফাংশন ব্যবহার করুন।
এটি হালনাগাদ হওয়া অবজেক্টটি রিটার্ন করে।
{name: "Jane", age: 42} | del(.age) # => {"name": "Jane"}
del-এর প্যারামিটার হলো একটি ইনডেক্স এক্সপ্রেশন (ডট বা ব্র্যাকেট নোটেশন ব্যবহার করে) যা অবজেক্টের একটি কী (key) নির্দেশ করে।
jq এটাকে পাথ এক্সপ্রেশন বলে।
শুধু একটি স্ট্রিং দিলেই হয় না।
{name: "Jane", age: 42} | del(name) # error: name/0 is not defined
{name: "Jane", age: 42} | del("name") # error: Invalid path expression with result "name"
{name: "Jane", age: 42} | del(.name) # OK
{name: "Jane", age: 42} | del(.["name"]) # OK
অবজেক্টে কোনো কী (key) আছে কি না পরীক্ষা করতে has ফাংশন ব্যবহার করুন।
{name: "Jane", age: 42} as $example
|
($example | has("name")), # => true
($example | has("sport")) # => false
in দিয়ে পরীক্ষা করুন, কোনো কী (key) অবজেক্টে আছে কি না।
{name: "Jane", age: 42} as $example
|
("name" | in($example)), # => true
("sport" | in($example)) # => false
সব কী (key)-এর একটি তালিকা আউটপুট করতে keys ফাংশন ব্যবহার করুন।
{name: "Jane", age: 42} | keys # => ["age", "name"]
লক্ষ্য করুন, keys কী (key)গুলোকে সর্ট করে দেয়।
আসল ক্রমে কী (key)গুলো পেতে keys_unsorted ব্যবহার করুন।
সব মান তালিকাভুক্ত করার মতো কোনো সমতুল্য ফাংশন নেই।
তবে .[] ফিল্টার অবজেক্টের মানগুলো একটি স্ট্রিম হিসেবে আউটপুট করে, আর সেই স্ট্রিমকে [...] অ্যারে কনস্ট্রাক্টর দিয়ে ধরে রাখা যায়।
[{first: "Jane", last: "Lopez", status: "awesome!"} | .[]]
# => ["Jane", "Lopez", "awesome!"]
map_values(filter) ফাংশনটি অবজেক্টের প্রতিটি মান-এ ফিল্টারটি প্রয়োগ করে।
{first: "Jane", last: "Lopez", status: "awesome!"}
| map_values(ascii_upcase)
# => {"first": "JANE", "last": "LOPEZ", "status": "AWESOME!"}
একটি অবজেক্টের উপর ইটারেট করতে হলে প্রথমে সেটিকে কী (key)-ভ্যালু অবজেক্টের একটি অ্যারে-তে রূপান্তর করতে হবে।
to_entries ফাংশন সেটাই করে।
{name: "Jane", age: 42} | to_entries'
# => [
# {
# "key": "name",
# "value": "Jane"
# },
# {
# "key": "age",
# "value": 42
# }
# ]
এই মুহূর্তে আমরা map-এর মতো অ্যারে ইটারেশন ফাংশন ব্যবহার করতে পারি।
from_entries ফাংশনটি এর বিপরীত: কী (key)-ভ্যালু অবজেক্টের একটি অ্যারেকে একটি অবজেক্টে রূপান্তর করা।
[
{"key":"name", "value":"Jane"},
{"key":"age", "value":42}
] | from_entries # =>{"name": "Jane", "age": 42}
একটি অবজেক্টের প্রতিটি কী (key)-ভ্যালু জোড়ায় একটি ফিল্টার প্রয়োগ করতে with_entries(filter) ফাংশন ব্যবহার করুন।
উদাহরণস্বরূপ, একটি নামকে একটি বয়সের সাথে ম্যাপ করা একটি অবজেক্ট দেওয়া থাকলে, কী (key) আর মানগুলোকে এভাবে অদলবদল করা যায়।
{"Jane": 42, "Richard": 54}
| with_entries({key: (.value | tostring), value: .key})
আউটপুট:
{
"42": "Jane",
"54": "Richard"
}
with_entries(filter) হলো নিচেরটির সমান:
to_entries | map(filter) | from_entries
এই অনুশীলনীতে আপনি আপনার এলাকার আর্কেড হলের সবচেয়ে জনপ্রিয় গেমটির হাই স্কোর হিসাব রাখার একটি উপায় তৈরি করবেন।
আপনার ৬টি ফাংশন লিখতে হবে, যেগুলোর বেশিরভাগই হাই স্কোর ধরে রাখা একটি অবজেক্ট নিয়ে কাজ করার সাথে সম্পর্কিত।
একটি ফাংশন create_score_board লিখুন, যা হাই স্কোর বোর্ড হিসেবে কাজ করে এমন একটি অবজেক্ট তৈরি করে।
এই অবজেক্টের কী (key) গুলো হবে খেলোয়াড়দের নাম, আর মান হবে তাদের স্কোর।
টেস্টের সুবিধার জন্য আপনি অবজেক্টটিতে সরাসরি একটি এন্ট্রি রাখতে চান।
এই প্রাথমিক এন্ট্রিতে খেলোয়াড়ের নাম হিসেবে "The Best Ever" এবং স্কোর হিসেবে 1000000 থাকা উচিত।
create_score_board
# returns an object with one initial entry
হাই স্কোর বোর্ডে একজন খেলোয়াড় যোগ করতে add_player ফাংশনটি লিখুন।
এটি ইনপুট হিসেবে একটি স্কোর বোর্ড নেয় এবং দুটি প্যারামিটার চায়: খেলোয়াড়ের নাম ও খেলোয়াড়ের স্কোর।
ফাংশনটি নতুন খেলোয়াড় যোগ করা স্কোর বোর্ড অবজেক্টটি আউটপুট দেয়।
{"José Valim", 486373}
| add_player("Dave Thomas"; 0)
# => {"Dave Thomas": 0, "José Valim": 486373} -- in some order
খেলোয়াড় যদি ইতিমধ্যেই বোর্ডে থাকে, তবে বোর্ডটি অপরিবর্তিত আউটপুট দিন।
খেলোয়াড়রা যদি আর্কেড হলের নিয়ম ভাঙে, তবে তাদের ম্যানুয়ালি হাই স্কোর বোর্ড থেকে সরিয়ে ফেলা হয়।
remove_player লিখুন, যা ইনপুট হিসেবে একটি বোর্ড এবং একটি প্যারামিটার নেয়: যে খেলোয়াড়কে সরাতে হবে তার নাম।
এই ফাংশনের উচিত বোর্ড থেকে নির্দিষ্ট খেলোয়াড়ের এন্ট্রিটি সরিয়ে ফেলা এবং নতুন বোর্ডটি আউটপুট দেওয়া।
খেলোয়াড় যদি শুরুতেই বোর্ডে না থাকে, তবে বোর্ডটির কিছুই হওয়া উচিত নয়; এটি যেমন আছে তেমনই রিটার্ন করা উচিত।
{"Dave Thomas": 0} | remove_player("Dave Thomas")
# => {}
{"Dave Thomas": 0} | remove_player("Rose Fanaras")
# => {"Dave Thomas": 0}
কোনো খেলোয়াড় আর্কেড হলে আরেকটি গেম শেষ করলে বোর্ডে তার আগের স্কোরের সাথে নির্দিষ্ট পরিমাণ পয়েন্ট যোগ হবে।
update_score লিখুন, যা ইনপুট হিসেবে একটি স্কোর বোর্ড নেয় এবং দুটি প্যারামিটার চায়: খেলোয়াড়ের নাম ও যে পরিমাণ স্কোর যোগ করতে হবে।
আপডেট হওয়ার পর ফাংশনটির উচিত স্কোর বোর্ডটি রিটার্ন করা।
{"Freyja Ćirić": 12771000} | update_score("Freyja Ćirić"; 73)
# => {"Freyja Ćirić": 12771073}
খেলোয়াড় আগে থেকে বোর্ডে না থাকলে এই ফাংশনের উচিত তাকে বোর্ডে যোগ করা।
আর্কেড হল সোমবারগুলোতে আলাদা একটি স্কোর বোর্ড রাখে। দিনের শেষে ওই বোর্ডের প্রতিটি খেলোয়াড় অতিরিক্ত ১০০ পয়েন্ট পায়।
apply_monday_bonus ফাংশনটি লিখুন।
ফাংশনটি ওই বোর্ডে থাকা প্রতিটি খেলোয়াড়ের জন্য বোনাস পয়েন্ট যোগ করে।
{
"Dave Thomas": 44,
"Freyja Ćirić": 539,
"José Valim": 265
}
| apply_monday_bonus
# => {"Dave Thomas": 144, "Freyja Ćirić": 639, "José Valim": 365}
কে সেরা খেলোয়াড়দের নিয়ে গড়ে উঠেছে তা নির্ধারণ করতে বিভিন্ন আর্কেড হল একে অপরের সাথে প্রতিযোগিতা করে। সবচেয়ে বেশি মোট স্কোর পাওয়া আর্কেডটি সম্মানটি জিতে নেয়।
একটি ফাংশন total_score লিখুন।
এটি ইনপুট হিসেবে একটি স্কোর বোর্ড নেয় এবং সব খেলোয়াড়ের স্কোরের যোগফল আউটপুট দেয়।
{
"Dave Thomas": 44,
"Freyja Ćirić": 539,
"José Valim": 265
}
| total_score
# => 848
Exercism-এ সাইন আপ করুন, jq ট্র্যাকের 12টি কনসেপ্ট75টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।