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. java-Mysql-SQLServer数据类型匹配速查表

    java-Mysql-SQLServer数据类型匹配速查表 Mysql ************************************ 当前列 ClassName ColumnType Di ...

  2. AE-模板替换->愉快今日--视频样片!

  3. JSP标准库标签 ———C标签

    一.C标签    一] <c:out value="..." default="..." escapeXml="true">   ...

  4. Windows 中默认安装的.Net 版本

    Windows contains a version of .NET by default. Here's a listing of them. XP .NET v1.0 -- Service pac ...

  5. COJ 0999 WZJ的数据结构(负一)

    WZJ的数据结构(负一) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 输入N个模板串Pi和文本串T,输出每个模板串Pi在T ...

  6. 【转】[教程]隐藏ActionBar中的MenuItem

    原文网址:http://blog.csdn.net/appte/article/details/12104823 有时候我们需要在不同的时候改变ActionBar中MenuItem的项数,或者隐藏某些 ...

  7. HTTP数据包头解析---之温故而知新!

    [转]HTTP请求模型和头信息参考 参考: http://blog.csdn.net/baggio785/archive/2006/04/13/661410.aspx模型: http://blog.c ...

  8. M0、M1、M2、M3都是用来反映货币供应量的重要指标

    m2-反映货币供应量的重要指标编辑词条m2广义货币是一个经济学概念,和狭义货币相对应,货币供给的一种形式或口径,以M2来表示,其计算方法是交易货币(M1,即社会流通货币总量加上活期存款)以及定期存款与 ...

  9. HDOJ(HDU) 1491 Octorber 21st

    Problem Description HDU's 50th birthday, on Octorber 21st, is coming. What an exciting day!! As a st ...

  10. 【2013南京区域赛】部分题解 hdu4802—4812

    上周末打了一场训练赛,题目是13年南京区域赛的 这场题目有好几个本来应该是我擅长的,但是可能是太久没做比赛了各种小错误代码写的也丑各种warusn trush搞得人很不爽 全场题之一的1002也没有想 ...