Golang: 解析JSON数据之二

上次我们介绍了 Go 语言中序列化和反序列化 JSON 数据的两个方法 Marshal() 和 Unmarshal(),并以示例演示了它们的用法。

我们在例子中看到,需要事先声明好对应的结构体,才能跟 JSON 字段映射起来。

有的时候,如果 JSON 数据的定义过于复杂,我们需要一种更加灵活的方式来处理。在这种情况下,可以将 JSON 数据映射到一个 map 结构中。

下面我们就来演示一下这种方式:

// 使用map结构 将JSON字符串转为对象

package main

import (
    "encoding/json"
    "fmt"
)

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

func main() {
    var bytes []byte
    var data map[string]interface{}

    // 先将字符串转为字节切片
    bytes = []byte(JSON)

    // 将字节切片映射到map上
    json.Unmarshal(bytes, &data)

    fmt.Println("group:", data["group"])

    // 转为[]interface{}类型
    persons := data["persons"].([]interface{})

    for index, item := range persons {
        // 类型转换
        person := item.(map[string]interface{})

        age := person["age"]

        // 更改年龄
        person["age"] = age.(float64) + 1

        // 打印最新个人信息
        fmt.Println("person", index, ":", person["name"].(string), age, "->", person["age"].(float64))
    }

    // 序列化为JSON字符串
    newBytes, _ := json.MarshalIndent(&data, "", "  ");

    // 打印新的JSON数据
    fmt.Println(string(newBytes))
}

在上面代码中,我们先定义了一个 map 变量,其 key 是 string 类型,value 是 interface{} 通用类型,这样可以兼容多种数据类型,在取值的时候进行一次类型转换即可。

之后我们调用 json.Unmarshal() 方法来将 JSON 字符串转为对象,这个我们前面也介绍过。

在转换完之后,取字段的时候我们应该以 map 的方式来执行,在取 persons 字段时,我们使用了下面这种方式:

// 转为[]interface{}类型
persons := data["persons"].([]interface{})

必选先转换为 []interface{} 类型,才能执行后续的 range 操作。在 range 内部,同样需要对当前遍历的对象做类型转换,才能安全地读写对象的数据。

最后,运行上面的程序,控制台打印内容如下:

group: programmer
person 0 : Jack 25 -> 26
person 1 : Lily 20 -> 21
{
  "group": "programmer",
  "persons": [
    {
      "age": 26,
      "name": "Jack"
    },
    {
      "age": 21,
      "name": "Lily"
    }
  ]
}
posted @ 2019-06-04 08:05  liuhe688  阅读(2836)  评论(0编辑  收藏  举报