JSON(Javascript Object Notation)是一种轻量级的数据交换语言,以文字为基础,具有自我描述性且易于让人阅读。尽管JSON是JavaScript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯。JSON与XML最大的不同在于XML是一个完整的标记语言,而JSON不是。JSON由于比XML更小、更快,更易解析,以及浏览器的內建快速解析支持,使得其更适用于网络数据传输领域。
解析到结构体
Go的JSON包中有如下函数
// json.go
package main import (
"encoding/json"
"fmt"
) type Server struct {
ServerName string
ServerIP string
} type Serverslice struct {
Servers []Server
} func main() {
var s Serverslice
str := `{"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},
{"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]}` json.Unmarshal([]byte(str), &s)
fmt.Println(s)
fmt.Println(s.Servers[0].ServerIP) }
outputs:
{[{Shanghai_VPN 127.0.0.1} {Beijing_VPN 127.0.0.2}]}
127.0.0.1
  首先定义了与json数据对应的结构体,数组对应slice,字段名对应JSON里面的KEY,在解析的时候,如何将JSON数据与struct字段相匹配呢?如JSON的key是Foo,那么怎么找对应的字段呢?
  • 首先查找tag含有Foo的可导出的struct字段(首字母大写)
  • 其次查找字段名是Foo的导出字段
  • 最后查找类似FOO或者FoO这样的除了首字母之外其他大小写不敏感的导出字段
  能够被赋值的字段必须是可导出字段(即首字母大写)。同时JSON解析的时候只会解析能找到的字段,如果找不到的字段会被忽略,这样的一个好处是:当你接收到一个很大的JSON数据结构而你却只想获取其中的部分数据的时候,你只需将你想要的数据对应的字段名大写,即可轻松解决问题。
 
解析到interface
  我们知道interface{}可以用来存储任意数据类型的对象,这种数据结构正好用于存储解析的未知结构的json数据的结果。JSON包中采用map[string]interface{}和[]interface{}结构来存储任意的JSON对象和数组。Go类型和JSON类型的对应关系如下:
  • bool代表JSON booleans
  • float64代表JSON numbers
  • string代表JSON strings
  • nil 代表JSON null
通过断言方式访问数据,如下例:
// tointer.go
package main import (
"encoding/json"
"fmt"
) func main() { b := []byte(`{"Name":"Wednesday", "Age":6, "Parents": [ "Gomez", "Moticia" ]}`)
var f interface{}
err := json.Unmarshal(b, &f)
if err != nil {
fmt.Println(err)
} m := f.(map[string]interface{}) for k, v := range m {
switch vv := v.(type) {
case string:
fmt.Println(k, "is string", vv)
case int:
fmt.Println(k, "is int", vv)
case []interface{}:
fmt.Println(k, "is an array:")
for i, u := range vv {
fmt.Println(i, u)
}
default:
fmt.Println(k, "is of a type I don't know how to handle")
}
} }
outputs:
  Name is string Wednesday
  Age is of a type I don't know how to handle
  Parents is an array:
  0 Gomez
  1 Moticia
通过上面的示例可以看到,通过interface{}与type assert的配合,我们就可以解析未知结构的JSON函数了。
生成JSON
若我们要输出JSON数据串,可通过Marshal函数来处理
func Marshal(v interface{})([]byte, error)
例:
// generalJson
package main import (
"encoding/json"
"fmt"
) type Server struct {
ServerName string `json:"serverName"`
ServerIP string `json:"serverIP"`
} type Serverslice struct {
Servers []Server `json:"servers"`
} func main() { var s Serverslice
s.Servers = append(s.Servers, Server{ServerName: "Shanghai_VPN", ServerIP: "127.0.0.1"})
s.Servers = append(s.Servers, Server{ServerName: "Beijing_VPN", ServerIP: "127.0.0.2"}) b, err := json.Marshal(s)
if err != nil {
fmt.Println("json err: ", err)
} fmt.Println(string(b)) }
outputs:
{"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},         {"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]}
 
  针对JSON的输出,我们在定义struct tag的时候需要注意几点:
  • 字段的tag是“-”,那么这个字段不会输出到JSON
  • tag中带有自定义名称,那么这个自定义名称会出现在JSON的字段名中,例如上面例子中的serverName
  • tag中如果带有“omitempty”选项,那么如果该字段值为空,就不会输出到JSON串中
  • 如果字段类型是bool,string,int,int64等,而tag中带有“,string”选项,那么这个字段在输出到JSON的时候会把该字段对应的值转换成JSON字符串
例:
// jsontest.go
package main import (
"encoding/json"
"os"
) type Server struct {
//ID不会导出到JSON
ID int `json:"-"` //ServerName的值会进行二次JSON编码
ServerName string `json:"serverName"`
ServerName2 string `json:"serverName2, string"` //如果ServerIP为空,则不输出到JSON中
ServerIP string `json:"serverIP,omitempty"`
Description string `json:"description,string"`
} func main() { s := Server{
ID: 3,
ServerName: `Go "1.0"`,
ServerName2: `Go "1.0"`,
ServerIP: ``,
Description: `描述信息`,
} b, _ := json.Marshal(s)
os.Stdout.Write(b) }
outputs:
{"serverName":"Go \"1.0\"","serverName2":"Go \"1.0\""}
 
  Marshal函数只有在转换成功的时候才会返回数据,在转换的过程中我们需要注意几点:
  • JSON对象只支持string作为key,所以要编码一个map,那么必须是map[string]T这种类型(T是Go语言中任意的类型)
  • Channel,complex和function是不能被编码成JSON的
  • 嵌套的数据时不能编码的,不然会让JSON编码进入死循环
  • 指针在编码的时候会输出指针指向的内容,而空指针会输出null
 
  目前bitly公司开源了一个叫做simplejson的包,在处理未知结构体的JSON时相当方便,地址:https://github.com/bitly/go-simplejson
 

Go 解析JSON的更多相关文章

  1. Xamarin.Android下获取与解析JSON

    一.新建项目 1.新建一个Android项目,并命名为为NetJsonList 2.右击引用,选择添加引用,引用System.Json.dll 二.同步请求 既然是跨平台,我们自然不能按照java下的 ...

  2. 使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON、.net 的json的序列化与反序列化(一)

    在开发中,我非常喜欢动态语言和匿名对象带来的方便,JSON.NET具有动态序列化和反序列化任意JSON内容的能力,不必将它映射到具体的强类型对象,它可以处理不确定的类型(集合.字典.动态对象和匿名对象 ...

  3. 阶段一:通过网络请求,获得并解析JSON数据(天气应用)

    “阶段一”是指我第一次系统地学习Android开发.这主要是对我的学习过程作个记录. 在上一篇阶段一:解析JSON中提到,最近在写一个很简单的天气预报应用.即使功能很简单,但我还是想把它做成一个相对完 ...

  4. 阶段一:解析JSON

    “阶段一”是指我第一次系统地学习Android开发.这主要是对我的学习过程作个记录. 最近学到解析JSON格式的网络数据,而作业也要求自己找一个天气预报的API地址,然后解析其中JSON格式的数据.可 ...

  5. C语言创建及解析Json的使用法则

    参考原文:http://blog.csdn.net/xukai871105/article/details/33013455 JSON(JavaScriptObject Notation)是一种轻量级 ...

  6. 不一样的dynamic解析json 万能方法

    写过javascript的人都知道js解析json 1:(JSON) 字符串转换为对象. var str = '{"name":"lsw","hobb ...

  7. C# 解析JSON的几种办法

    欲成为海洋大师,必知晓海中每一滴水的真名. 刚开始只是想找一个转换JSON数组的方法,结果在MSDN翻到一大把. 搜索过程中免不了碰到一大堆名词:WCF => DataContract => ...

  8. eval解析JSON中的注意点

       在JS中将JSON的字符串解析成JSON数据格式,一般有两种方式: 1.一种为使用eval()函数. 2. 使用Function对象来进行返回解析. 使用eval函数来解析,并且使用jquery ...

  9. C#解析json文件的方法

    C# 解析 json JSON(全称为JavaScript Object Notation) 是一种轻量级的数据交换格式.它是基于JavaScript语法标准的一个子集. JSON采用完全独立于语言的 ...

  10. WP8解析JSON格式(使用DataContractJsonSerializer类)(推荐)

    DataContractJsonSerializer是.NET自带的类,在解析JSON格式的时候使用起来方便快捷,至于生成方面由于暂时没用到就没去看了.使用需要引用System.Runtime.Ser ...

随机推荐

  1. 导出函数结构 EXPORT_DIRECTORY

    typedef struct _IMAGE_EXPORT_DIRECTORY { DWORD Characteristics; DWORD TimeDateStamp; //输出表的创建时间 WORD ...

  2. linux下一些很有用的命令

    ps -ef | grep keepalive | grep -v grep | awk '{print $2}' | xargs kill -9 wget --random-wait -r -p - ...

  3. laravel和dingoapi的结合使用

    dingoapi是一个laravel的开源插件,可以在github上搜索到,现在在做一个项目,项目中总是会有后端跟前端的json数据交互,而这个dingoapi为json交互提供了很大的便利. 先安装 ...

  4. Linq中join & group join & left join 的用法

    Linq中join & group join & left join 的用法 2013-01-30 11:12 12154人阅读 评论(0) 收藏 举报  分类: C#(14)  文章 ...

  5. API认证方法一览

    Open api authentication Amazon DigitalOcean Webchat Weibo QQ Amazon Web Services HMAC Hash Message A ...

  6. jquery+css实现菜单收缩效果并适应多种浏览器与移动平台

    效果 出现 css部分 .content-wrapper{ -webkit-transition: -webkit-transform .3s ease-in-out, margin .3s ease ...

  7. hdu-1800

    思路: 这题被坑的不轻. 首先花了一段时间想明白了思路是要找出现次数最多数字,以为这题就这样解决了,结果发现每个数字的最大长度是30,long long都装不下,因此就要用字符串来保存处理.然后在in ...

  8. HDU-1047(DP-二进制状态压缩)

    Problem Description Ignatius has just come back school from the 30th ACM/ICPC. Now he has a lot of h ...

  9. 原来你们是这种key-value存储

    上周毛老师,在内部分享为我们扫盲了一下Memcached和Redis的支持,讲了很多东西,我一般比较懒不愿意去记东西喜欢把总结成blog,当我忘记的时候可以回头看看.好的废话就说这么多.先看Memca ...

  10. html——基础样式篇(1)

    格式化标签 <b>字体加粗标签 <i>字体斜体标签 <sub>下标标签 <sup>上标标签 <del>删除标签 //这在商品特价时常使用 a ...