1. 从string到json格式的golang对象

首先将合法的json格式string或者yaml格式string解析为golang对象

  • json格式为:
import "encoding/json"
var json_data interface{}
json.Unmarshal([]byte(json_str), &json_data)
json_strinterface{}
  • yaml格式为:
import (
    yaml "gopkg.in/yaml.v3"
)
var json_data interface{}
yaml.Unmarshal([]byte(yaml_str), &json_data)
yaml_str

2. 从golang对象中根据路径提取值

路径格式点分割的键,所以需要一个键是数字时转化为数组下标取值的操作

import "unicode"
func isdigit(s string) bool {
    for _, r := range s {
        if !unicode.IsDigit(r) {
            return false
        }
    }
    return true
}

定义一个函数递归根据路径选择值,注意没有异常处理

import "strconv"

func getIn(obj interface{}, path []string) interface{} {
    if len(path) == 0 {
        return obj
    }
    var key = path[0]

    if isdigit(key) {
        i, _ := strconv.ParseInt(key, 10, 32)
        t := obj.([]interface{})
        return getIn(t[i], path[1:])
    } else {
        t := obj.(map[string]interface{})
        return getIn(t[key], path[1:])
    }
}

定义一个入口函数,键使用字符串形式传递

func jsonGet(json_obj interface{}, key string) interface{} {
    if key == "" {
        return json_obj
    }
    return getIn(json_obj, strings.Split(key, "."))
}

以下为main函数,使用实例


func main() {
    var json_str string = `{
        "name": {"first": "Tom", "last": "Anderson"},
        "age":37,
        "children": ["Sara","Alex","Jack"],
        "fav.movie": "Deer Hunter",
        "friends": [
          {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
          {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
          {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
        ]
      }
    `
    var json_data interface{}
    json.Unmarshal([]byte(json_str), &json_data)
    fmt.Println(jsonGet(json_data, "name.last"))
    fmt.Println(jsonGet(json_data, "friends.1.nets.1"))
}

3.完整代码

// main.go
package main

import (
    "encoding/json"
    "fmt"
    "strconv"
    "strings"
    "unicode"
)

func isdigit(s string) bool {
    for _, r := range s {
        if !unicode.IsDigit(r) {
            return false
        }
    }
    return true
}

func getIn(obj interface{}, path []string) interface{} {
    if len(path) == 0 {
        return obj
    }
    var key = path[0]

    if isdigit(key) {
        i, _ := strconv.ParseInt(key, 10, 32)
        t := obj.([]interface{})
        return getIn(t[i], path[1:])
    } else {
        t := obj.(map[string]interface{})
        return getIn(t[key], path[1:])
    }
}

func jsonGet(json_obj interface{}, key string) interface{} {
    if key == "" {
        return json_obj
    }
    return getIn(json_obj, strings.Split(key, "."))
}

func main() {
    var json_str string = `{
        "name": {"first": "Tom", "last": "Anderson"},
        "age":37,
        "children": ["Sara","Alex","Jack"],
        "fav.movie": "Deer Hunter",
        "friends": [
          {"first": "Dale", "last": "Murphy", "age": 44, "nets": ["ig", "fb", "tw"]},
          {"first": "Roger", "last": "Craig", "age": 68, "nets": ["fb", "tw"]},
          {"first": "Jane", "last": "Murphy", "age": 47, "nets": ["ig", "tw"]}
        ]
      }
    `
    var json_data interface{}
    json.Unmarshal([]byte(json_str), &json_data)
    fmt.Println(jsonGet(json_data, "name.last"))
    fmt.Println(jsonGet(json_data, "friends.1.nets.1"))
}

  • 运行
$ go run main.go
Anderson
tw

更多介绍

有很多开源库也可以处理类似自由结构的json数据,下面列几个供参考