Golang: 解析JSON數據之一


JSON 作為目前最流行的數據傳輸格式, 相信每個程序員都跟它打過交道吧。使用 Go 語言時,也不可避免的要操作 JSON 數據,令人驚喜的是,Go 內置了序列化和反序列化 JSON 的功能,今天就來總結一下。

序列化是將結構對象轉為 JSON 字符串,反序列化是將 JSON 字符串轉為結構對象,它們分別對應 encoding/json 包下面的兩個方法:

// 序列化 接收interface{}參數 返回字節切片
func Marshal(v interface{}) ([]byte, error) { }

// 反序列化 接收字節切片和interface{}參數 將結果反映在interface{}結構上
func Unmarshal(data []byte, v interface{}) error { }

marshal 這個單詞的含義是 整理、編排、排列,對應的操作是將結構對象編排成 JSON 字符串,反之,unmarshal 是它的逆操作。

我們通過一個例子來演示這兩個方法。假如我們有如下 data.json 文件:

{
  "group": "programmer",
  "persons": [
    {
      "name": "Jack",
      "age": 25
    },
    {
      "name": "Lily",
      "age": 20
    }
  ]
}

接下來,我們要讀取這個文件,將 JSON 內容轉為結構對象,然后更改對象數據:

// 讀取JSON文件 將內容轉為結構對象 然后更改數據

package main

import (
    "encoding/json"
    "fmt"
    "io/ioutil"
)

type (
    person struct {
        Name string `json:"name"`
        Age  int    `json:"age"`
    }

    result struct {
        Group string `json:"group"`
        Persons []person `json:"persons"`
    }
)

func main() {
    var data result

    // 讀取JSON文件內容 返回字節切片
    bytes, _ := ioutil.ReadFile("data.json")

    fmt.Println("*** data.json content: ***")

    // 打印時需要轉為字符串
    fmt.Println(string(bytes))

    // 將字節切片映射到指定結構上
    json.Unmarshal(bytes, &data)

    fmt.Println("*** unmarshal result: ***")

    // 打印對象結構
    fmt.Println(data)

    // 更改數據
    data.Group = "engineer"

    // 將更改后的結構對象序列化成JSON格式
    newBytes, _ := json.Marshal(&data)

    fmt.Println("*** update content: ***")

    // 打印JSON結果
    fmt.Println(string(newBytes))
}

上面代碼中,結構體字段的后面都有一串說明性信息,它們被稱為標簽(Tag),用於將結構體和 JSON 數據映射起來,如果不指定,系統會嘗試以大小寫無關的方式去匹配,但為了便於閱讀和避免不必要的匹配過程,我們這里手動指定了具體的字段。

我們運行該程序,控制台會打印如下信息:

{
  "group": "programmer",
  "persons": [
    {
      "name": "Jack",
      "age": 25
    },
    {
      "name": "Lily",
      "age": 20
    }
  ]
}
*** unmarshal result: ***
{programmer [{Jack 25} {Lily 20}]}
*** update content: ***
{"group":"engineer","persons":[{"name":"Jack","age":25},{"name":"Lily","age":20}]}

最后的 JSON 數據還可以在格式化一下,我們可以利用下面這個方法:

// 帶格式化的反序列化方法
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) { }

相比 Marshal() 方法,MarshalIndent() 多了兩個參數,分別是前綴和縮進,都是字符串類型。前綴一般不怎么常用,縮進可指定若干個空格,下面我們來改造一下:

// 將更改后的結構對象序列化成JSON格式
newBytes, _ := json.MarshalIndent(&data, "", "  ")

fmt.Println("*** indent content: ***")

// 打印JSON結果
fmt.Println(string(newBytes))

再次運行程序,打印結果如下:

*** indent content: ***
{
  "group": "engineer",
  "persons": [
    {
      "name": "Jack",
      "age": 25
    },
    {
      "name": "Lily",
      "age": 20
    }
  ]
}

最后,如果希望將結果寫回到配置文件中的話,可以添加下面這一行代碼:

ioutil.WriteFile("data.json", newBytes, os.ModeAppend)

WriteFile() 方法需要三個參數:文件名、字節切片數據、指定的文件操作權限。如果文件存在,這個方法先會清空文件內容,然后再寫入新數據,如果文件不存在,則根據指定的第三個參數,去先創建指定的文件。

執行完上面這行代碼,再去查看之前的 data.json 文件,就會發現,配置內容已經更新了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM