4.8.1 مقدمه #
JSON یک فرمت متنی است که برای مبادله و ذخیره دادهها استفاده میشود. نام JSON مخفف عبارت JavaScript Object Notation است و در ابتدا به عنوان یک زبان مبتنی بر جاوااسکریپت توسعه یافته است. با این حال، در حال حاضر JSON به راحتی با بیشتر زبانهای برنامهنویسی سازگار است.
JSON یک مجموعه از جفتهای «key: value» است که با کاما از یکدیگر جدا شدهاند و بین آنها با «:» ارتباط دارند. JSON در بین برنامهنویسان به عنوان یک ساختار دادهای محبوب است و به راحتی دادهها را به صورت ساختاردهی شده در برنامههای کاربردی مختلف به کار میرود. این فرمت دیتا استاندارد و مستقل از زبانها و پلتفرمهای برنامهنویسی است و برای برنامههای تحت وب، موبایل، دسکتاپ و سرور قابل استفاده است.
ساختار یک فایل JSON شامل تعدادی از آبجکتها و آرایهها میباشد. به عبارتی دادههای JSON میتوانند در سه نوع اصلی “جسم آرکی”(object) ، “کالکشن آرای”(array) و “مقادیر اولیه”(values) تعریف شوند. آبجکت یک گروه از خصوصیات است که دارای یک کلید منحصر به فرد به عنوان “عنوان شی” میباشد. همچنین، آرایه نیز به مثابه یک لیست یا آرایه از خصوصیات است.
یک مثال ساده JSON:
1{
2 "name": "John Doe",
3 "age": 30,
4 "email": "[email protected]",
5 "address": {
6 "street": "123 Main St",
7 "city": "Anytown",
8 "state": "CA",
9 "zip": "12345"
10 },
11 "phone": [
12 {
13 "type": "home",
14 "number": "555-555-1234"
15 },
16 {
17 "type": "work",
18 "number": "555-555-5678"
19 }
20 ]
21}
در این مثال، یک شیء با عنوان “John Doe” تعریف شده است. این شیء دارای خصوصیاتی همچون نام، سن، ایمیل، آدرس و تلفن است. آدرس نیز یک شیء است که شامل خصوصیاتی همچون خیابان، شهر، ایالت و کد پستی است. همچنین، تلفن به عنوان یک آرایه از شیءها تعریف شده است که شامل نوع تلفن و شماره تلفن است.
4.8.2 کار با marshal و unmarshal پکیج json #
در زبان برنامهنویسی Go، پکیج “encoding/json” برای کار با دادههای JSON بسیار مفید است. این پکیج امکاناتی برای تبدیل دادههای Go به فرمت JSON (marshal) و برعکس (unmarshal) در اختیار برنامهنویسان قرار میدهد.
4.8.2.1 کار با marshal #
با استفاده از تابع “Marshal”، برای مثال، میتوان یک شیء با فرمت JSON تولید کرد. در کد زیر، یک شیء از نوع “person” تعریف شده است و با استفاده از تابع “Marshal” به فرمت JSON تبدیل شده است:
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6)
7
8type person struct {
9 Name string `json:"name"`
10 Age int `json:"age"`
11 Email string `json:"email"`
12}
13
14func main() {
15 p := &person{Name: "John Doe", Age: 30, Email: "[email protected]"}
16
17 b, err := json.Marshal(p)
18 if err != nil {
19 fmt.Println("error:", err)
20 }
21
22 fmt.Println(string(b))
23}
1$ go run main.go
2{"name":"John Doe","age":30,"email":"[email protected]"}
در کد بالا، ابتدا یک شیء از نوع “person” با مقادیر مشخص تعریف شده است. سپس از تابع “Marshal” برای تبدیل این شیء به فرمت JSON استفاده شده است. خروجی تابع “Marshal” یک بایتآرایه است که به عنوان یک رشته و با استفاده از تبدیل به “string” چاپ شده است.
4.8.2.2 کار با unmarshal #
با استفاده از تابع “Unmarshal” نیز میتوان یک رشته JSON را به شیء Go تبدیل کرد. در کد زیر، یک رشته JSON با نام “data” تعریف شده است و با استفاده از تابع “Unmarshal” به یک شیء از نوع “person” تبدیل شده است:
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6)
7
8type person struct {
9 Name string `json:"name"`
10 Age int `json:"age"`
11 Email string `json:"email"`
12}
13
14func main() {
15 data := `{"name":"John Doe","age":30,"email":"[email protected]"}`
16
17 var p person
18 err := json.Unmarshal([]byte(data), &p)
19 if err != nil {
20 fmt.Println("error:", err)
21 }
22
23 fmt.Println(p.Name, p.Age, p.Email)
24}
1$ go run main.go
2John Doe 30 [email protected]
در کد بالا، ابتدا یک رشته JSON با نام “data” تعریف شده است. سپس یک شیء از نوع “person” با استفاده از تابع “Unmarshal” و با این رشته JSON به شکل مقداردهی شده است. خروجی تابع “Unmarshal”، شیء “person” است که بعداً در کد چاپ شده است. توجه داشته باشید که در اینجا از “[]byte” برای تبدیل رشته به بایتآرایه استفاده شده است.
4.8.3 تبدیل آرایه و slice به json #
در Go، میتوان آرایهها و sliceها را به فرمت JSON تبدیل کرد. برای این کار، از تابع “Marshal” پکیج “encoding/json” استفاده میشود.
برای مثال، فرض کنید یک slice از اعداد صحیح داشته باشیم. برای تبدیل این slice به فرمت JSON، کد زیر نمونهای از چگونگی استفاده از تابع “Marshal” را نشان میدهد:
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6)
7
8func main() {
9 numbers := []int{1, 2, 3, 4, 5}
10
11 data, err := json.Marshal(numbers)
12 if err != nil {
13 fmt.Println("error:", err)
14 }
15
16 fmt.Println(string(data))
17}
در این کد، ابتدا یک slice از اعداد صحیح تعریف شده است. سپس با استفاده از تابع “Marshal” این slice به فرمت JSON تبدیل شده و در متغیر “data” ذخیره شده است. در نهایت، با استفاده از تبدیل به “string”، خروجی تابع “Marshal” به صورت یک رشته چاپ شده است.
همچنین، میتوان آرایههای مولتیبعد را نیز به فرمت JSON تبدیل کرد. در کد زیر، یک آرایه دوبعدی از اعداد صحیح تعریف شده است و به فرمت JSON تبدیل میشود:
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6)
7
8func main() {
9 var matrix [2][3]int = [2][3]int{{1, 2, 3}, {4, 5, 6}}
10
11 data, err := json.Marshal(matrix)
12 if err != nil {
13 fmt.Println("error:", err)
14 }
15
16 fmt.Println(string(data))
17}
در این کد نیز، بعد از تعریف یک آرایه دوبعدی از اعداد صحیح، با استفاده از تابع “Marshal” آن را به فرمت JSON تبدیل شده و در متغیر “data” ذخیره شده است. خروجی تابع “Marshal” نیز به صورت یک رشته چاپ میشود.
4.8.4 تبدیل map به json #
در Go، میتوان map را به فرمت JSON تبدیل کرد با استفاده از تابع “Marshal” پکیج “encoding/json”.
برای مثال، فرض کنید یک map از دادههای شخصی داشته باشیم که شامل نام، سن و ایمیل است. برای تبدیل این map به فرمت JSON، کد زیر نمونهای از چگونگی استفاده از تابع “Marshal” را نشان میدهد:
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6)
7
8func main() {
9 data := map[string]interface{}{
10 "name": "John Doe",
11 "age": 30,
12 "email": "[email protected]",
13 }
14
15 output, err := json.Marshal(data)
16 if err != nil {
17 fmt.Println("error:", err)
18 }
19
20 fmt.Println(string(output))
21}
1$ go run main.go
2{"age":30,"email":"[email protected]","name":"John Doe"}
در کد بالا، یک map از دادههای شخصی با نام “data” تعریف شده است و سپس با استفاده از تابع “Marshal” به فرمت JSON تبدیل شده است. خروجی تابع “Marshal” نیز به صورت یک رشته چاپ شده است.
توجه داشته باشید که در این نمونه، نوع دادهی مقدارهای مپ از نوع خاصی استفاده نشده است و به جای آن، از نوع “interface{}” برای مقادیر استفاده شده است. این به این دلیل است که ممکن است مقادیر مختلفی در map وجود داشته باشد ولی نوعشان کاملاً شناخته شده نباشد. با استفاده از “interface{}"، مقادیر به صورت پویا تعریف شده و برنامه قادر است به درستی تبدیل را انجام دهد.