zoukankan      html  css  js  c++  java
  • 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 文件,就会发现,配置内容已经更新了。

  • 相关阅读:
    68
    56
    Django manager 命令笔记
    Django 执行 manage 命令方式
    Django 连接 Mysql (8.0.16) 失败
    Python django 安装 mysqlclient 失败
    H.264 SODB RBSP EBSP的区别
    FFmpeg—— Bitstream Filters 作用
    MySQL 远程连接问题 (Windows Server)
    MySQL 笔记
  • 原文地址:https://www.cnblogs.com/liuhe688/p/10971327.html
Copyright © 2011-2022 走看看