加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

golang 读取JSON文件(读书笔记)

发布时间:2020-12-16 19:01:32 所属栏目:大数据 来源:网络整理
导读:JSON(JavaScript Object Notation)是一种比XML更轻量级的数据交换格式,在易于人们阅读和编写的同时,也易于程序解析和生成。尽管JSON是JavaScript的一个子集,但JSON采用完全独立于编程语言的文本格式,且表现为key/value的文本描述形式(与GO语言中的map

JSON(JavaScript Object Notation)是一种比XML更轻量级的数据交换格式,在易于人们阅读和编写的同时,也易于程序解析和生成。尽管JSON是JavaScript的一个子集,但JSON采用完全独立于编程语言的文本格式,且表现为key/value的文本描述形式(与GO语言中的map极为相似),这使它成为较理想的、跨平台的、跨语言的数据交换语言。记得初次接触JSON这种数据形式是在刚工作时,当时在js页面中处理非常方便,印象一直很深刻。后来,学习了一些mongodb,完全处理这种格式的数据。原来,个人很不喜欢像这种键-值对的数据形式,因为总觉得这个底层可能映射起来比较方便,不过,好多情况下确实是少不了这种形式。

Go语言内建对JSON的支持,使用GO语言内置的encoding/json标准库,开发者可以轻松使用GO程序生成和解析JSON格式的数据。


举个例子:

package main
import (
    "encoding/json"
    "fmt"
)
type Book struct {
    Title       string
    Author      []string
    Publisher   string
    Price       float64
    IsPublished bool
}
func main() {
    b := []byte(`{
    "Title":"go programming language","Author":["john","ada","alice"],"Publisher":"qinghua","IsPublished":true,"Price":99
  }`)
//先创建一个目标类型的实例对象,用于存放解码后的值
    var book Book
    err := json.Unmarshal(b,&book)
    if err != nil {
        fmt.Println("error in translating,",err.Error())
        return
    }
    fmt.Println(book.Author)
}

Json.Unmarshal()函数会根据一个约定的顺序查找目标结构中的字段,如果找到一个则进行匹配。这些字段在类型声明中必须都是以大写字母开头、可被导出的字段。

但是当JSON数据中的数据结构和GO中的目标类型不匹配时,会怎样呢?如果JSON中的字段在GO目标类型中不存在,json.Unmarshal()函数在解码过程中会丢弃该字段。这个特性让我们可以从一段JSON数据中筛选出指定的值填充到多个GO语言类型中,当然,前提是已知JSON数据的字段结构。这也意味着,目标类型中不可被导出的私有字段(非首字母大写)将不会受到解析转化的影响,

如果要解析一个配置文件,为了使程序端的改动能够灵活,大多数情况下是不知道配置文件中到底是怎样的结构,只是在需要的时候去取就可以了。GO语言支持接口。在go中,接口是一组预定义方法的组合,任何一个类型均可通过实现接口预定义的方法来实现,且无需显示声明,所以没有任何方法的空接口代表任何类型。换句话说,每一个类型其实都至少实现了一个空接口。GO内建这样灵活的类型系统,向我们传达了一个很有价值的信息:空接口是通用类型。如果要解析一段未知结构的JSON,只需向这段JSON数据解码输出到一个空接口即可。在GO的标准库encoding/json包中,允许使用map[string]interface{}和[]interface{}类型的值来分别存放未知结构的JSON对象或数组。

还是刚才的例子,只是将结构体去掉,变成一个未知结构的数据。

package main
import (
    "encoding/json"
    "fmt"
)
func main() {
    b := []byte(`{
    "Title":"go programming language","Price":99
  }`)
    //先创建一个目标类型的实例对象,用于存放解码后的值
    var inter interface{}
    err := json.Unmarshal(b,&inter)
    if err != nil {
        fmt.Println("error in translating,err.Error())
        return
    }
    //要访问解码后的数据结构,需要先判断目标结构是否为预期的数据类型
    book,ok := inter.(map[string]interface{})
    //然后通过for循环一一访问解码后的目标数据
    if ok {
        for k,v := range book {
            switch vt := v.(type) {
            case float64:
                fmt.Println(k," is float64 ",vt)
            case string:
                fmt.Println(k," is string ",vt)
            case []interface{}:
                fmt.Println(k," is an array:")
                for i,iv := range vt {
                    fmt.Println(i,iv)
                }
            default:
                fmt.Println("illegle type")
            }
        }
    }
}

说实话,这样转化确实很繁琐,但也是解析未知结构的JSON数据的方式。

原来试图使用XML来做配置文件,但是,那样的话必须要知道有哪些数据项(Key),而对于灵活的配置文件来说,到底包括哪些是没有办法提前预知的,而各个模块需要哪些数据的时候只需到公共信息中去提取就好了,主程序也不需要知道到底有哪些信息是公用的,它只要负责将消息以键值对的形式保存起来供子程序调用就可以了。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读