通常使用Golang encoding/json 标准库可以方便的编码/解析JSON数据,但是前提需要定义struct数据结构。特别是解析未知结构的JSON数据时,原有方法很难满足需求了,本文主要介绍动态解析JSON格式。
Go语言的JSON 库
Go语言自带的JSON转换库为 encoding/json
1.1)其中把对象转换为JSON的方法(函数)为 json.Marshal(),其函数原型如下
func Marshal(v interface{}) ([]byte, error)
也就是说,这个函数接收任意类型的数据 v,并转换为字节数组类型,返回值就是我们想要的JSON数据和一个错误代码。当转换成功的时候,这个错误代码为nil
在进行对象转换为 JSON 的过程中,会遵循如下几条规则:
1.2)把 JSON 转换回对象的方法(函数)为 json.Unmarshal(),其函数原型如下
func Unmarshal(data [] byte, v interface{}) error
这个函数会把传入的 data 作为一个JSON来进行解析,解析后的数据存储在参数 v 中。这个参数 v 也是任意类型的参数(但一定是一个类型的指针),原因是我们在是以此函数进行JSON 解析的时候,这个函数不知道这个传入参数的具体类型,所以它需要接收所有的类型。
那么,在进行解析的时候,如果JSON 和 对象的结构不对口会发生什么呢,这就需要解析函数json.Unmarshal()遵循以下规则
json.Unmarshal() 函数会根据一个约定的顺序查找目标结构中的字段,如果找到一个即发生匹配。那什么是找到了呢?关于“找到了”又有如下的规则:假设一个JSON对象有个名为"Foo"的索引,要将"Foo"所对应的值填充到目标结构体的目标字段上,json.Unmarshal() 将会遵循如下顺序进行查找匹配
注意:如果JSON中的字段在Go目标类型中不存在,json.Unmarshal() 函数在解码过程中会丢弃该字段。
当JSON 的结构是未知的时候,会遵循如下规则:
注意:在Go的标准库encoding/json包中,允许使用map[string]interface{}和[]interface{} 类型的值来分别存放未知结构的JSON对象或数组
1、传统方法
比如 User 数据结构如下:
type User struct { Name string `json:"name"` Age int `json:"age"` }
在定义struct字段的时候,可以在字段后面添加tag,来控制encode/decode的过程:是否要 decode/encode 某个字段,JSON 中的字段名称是什么。字段名首字母控制字段的可见性,若要输出到JSON,首字母需要大写。
三种tag:
- :不要解析这个字段
omitempty :当字段为空(默认值)时,不要解析这个字段。比如 false、0、nil、长度为 0 的 array,map,slice,string
FieldName :当解析 json 的时候,使用这个名字
举例来说吧:
// 解析的时候忽略该字段。默认情况下会解析这个字段,因为它是大写字母开头的 Field int `json:"-"` // 解析(encode/decode) 的时候,使用 `other_name`,而不是 `Field` Field int `json:"other_name"` // 解析的时候使用 `other_name`,如果struct 中这个值为空,就忽略它 Field int `json:"other_name,omitempty"`
(1)encode
user := User{Name: "test", Age:23} data, err := json.Marshal(user) if err != nil { fmt.Println(string(data)) }
data 就是 []byte 类型的数组,里面包含了解析为 JSON 之后的数据,可以使用string(data)转型为string。
(2)decode
要把JSON数据转换成Go类型的值(Decode),可以使用 json.Unmarshal 。
var user User err = json.Unmarshal(data, &user) if err != nil { fmt.Errorf("Can not decode data: %v\n", err) }
2、动态解析
动态JSON结构未知,若使用前面方法需要事先定义数据结构,这与PHP/Python JSON处理非常不同。若不考虑性能,使用simplejson。
(1)simplejson
js, err := simplejson.NewJson([]byte(`{ "test": { "string_array": ["asdf", "zxcv"], "array": [1, "2", 3], "arraywithsubs": [{"subkeyone": 1}, "bignum": 9223372036854775807, "string": "simplejson", "bool": true } }`)) if err != nil { panic("json format error") } //获取某个字段值 s, err := js.Get("test").Get("string").String() if err != nil { panic(err) } fmt.Println(s) //检查某个字段是否存在 _, ok := js.Get("test").CheckGet("string2") if ok { fmt.Println("存在!") } else { fmt.Println("不存在") }
(2)interface
比如JSON有以下两种类型:
{"Type":"sound","Msg":{"Description":"dynamite","Authority":"the Bruce Dickinson"}} {"Type":"cowbell","Msg":{"More":true}}
Msg 具体什么类型实现无法判断, Msg being a map[string]interface{} :
type Envelope struct { Type string Msg interface{} } var env Envelope if err := json.Unmarshal([]byte(input), &env); err != nil { log.Fatal(err) } // for the love of Gopher DO NOT DO THIS var desc string = env.Msg.(map[string]interface{})["description"].(string) fmt.Println(desc)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍在Go语言程序中使用gojson来解析JSON格式文件,包括了在Go语言程序中使用gojson来解析JSON格式文件的使用技巧和注意事项,需要的朋友参考一下 gojson是快速解析json数据的一个golang包,你使用它可以快速的查找json内的数据 安装 使用简介 结构 (1) func Json(data) *Js data为string类型,初始化Js结构,解析json并且r
本文向大家介绍在Go语言中使用JSON的方法,包括了在Go语言中使用JSON的方法的使用技巧和注意事项,需要的朋友参考一下 Encode 将一个对象编码成JSON数据,接受一个interface{}对象,返回[]byte和error: Marshal函数将会递归遍历整个对象,依次按成员类型对这个对象进行编码,类型转换规则如下: bool类型 转换为JSON的Boolean 整数,浮点数等数值类型
所以我尝试了一些基于我代码中的例子的东西,没有得到数据,但也没有错误。代码是: 我用测试 Curl-X POST-H"接受:应用程序/json"--data"{\"用户名\":\"x\",\"密码\":\"y\"}"127.0.0.1:8000/login-i 服务器会打印出: 证书:, 为什么cred.usernamecred.password?
本文向大家介绍go语言使用scp的方法实例分析,包括了go语言使用scp的方法实例分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了go语言使用scp的方法。分享给大家供大家参考。具体如下: 希望本文所述对大家的Go语言程序设计有所帮助。
问题内容: 我有一些用于处理YAML配置文件的代码,该文件有点失控,带有类型断言,我觉得必须有更好的方法来做到这一点。 这是我的配置文件中的相关代码段: 这是我的解析代码: 该代码按预期工作,但是这里有很多类型断言,我无法撼动自己缺少更好的方法的感觉。 正如配置所暗示的那样,可能要注意的一个关键项目是Caddy风格的插件系统的配置,因此主配置解析器无法提前知道插件配置的外观。它必须将对配置文件的插
本文向大家介绍Go语言使用MySql的方法,包括了Go语言使用MySql的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Go语言中使用MySql的方法。分享给大家供大家参考。具体如下: 此代码需要先安装mysql的go语言驱动。 首先安装mysql的go语言驱动: 示例代码如下: 希望本文所述对大家的Go语言程序设计有所帮助。