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

      

          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",
    "Author":["john","ada","alice"],
    "Publisher":"qinghua",
    "IsPublished":true,
    "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),而对于灵活的配置文件来说,到底包括哪些是没有办法提前预知的,而各个模块需要哪些数据的时候只需到公共信息中去提取就好了,主程序也不需要知道到底有哪些信息是公用的,它只要负责将消息以键值对的形式保存起来供子程序调用就可以了。



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值