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中ExecutorService接口

    一.声明 public interface ExecutorService extends Executor 位于java.util.concurrent包下 所有超级接口:Executor 所有已知 ...

  2. WCF入门教程[WCF基本应用]

    一.概述 Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口,它是.NET框架的一部分.由 .NE ...

  3. 2015年6月股灾永远载入A股史册

    之前很奇怪这次牛市行情的暴涨与暴跌,后来发现成交量是以往不可想象的,而这一切的源头就是融资融券,也就是杠杆. 杠杆的作用是无穷的,就像阿基米德说的那样“给我一个支点,我就能撬起地球”. 杠杆是个放大器 ...

  4. shell脚本实例一,移动文件夹中大于2000B的文件到另一个文件夹

    shell脚本能帮我们简化linux下的一些工作,现在有个需求,把TMPA文件夹下大于2000B的文件都移动到TMPB下 #! /bin/bash function movefiles() { ` d ...

  5. ExpandableList列表的简单应用

    package com.test;//Download by http://ww.codefans.netimport java.util.ArrayList;import java.util.Has ...

  6. QML控件类关系图

    花了点时间整理了下QML控件之间的关系图和QML控件和C++类的对应关系,基于Qt5.6版本 其他版本可能会有差异 图片像素比较大,另存为后放大图片就可以看清楚了 工程下载地址 QMLClassDia ...

  7. Xamarin devexpress Grid

    Devexpress 提供了datagrid 控件对于xamarin 进行支持.整个世界美好了,已经无法用语言来形容一个 被列表控件折磨的要死的人看到熟悉的图标时候的激动了.还有一点引用官网的原话: ...

  8. 【转】Java 多线程(四) 多线程访问成员变量与局部变量

    原文网址:http://www.cnblogs.com/mengdd/archive/2013/02/16/2913659.html 先看一个程序例子: public class HelloThrea ...

  9. linux串口驱动分析——发送数据

    一.应用程序中write函数到底层驱动历程 和前文提到的一样,首先先注册串口,使用uart_register_driver函数,依次分别为tty_register_driver,cdev_init函数 ...

  10. AOJ 0033 深度优先搜索

    题意:按给定顺序从A口放标号位1-10的10个球,利用挡板可以使球落到B或C,问能否使B和C里的球标号从下往上递增. 分析:对于第 i 个球,若a[i]大于B口上方的球,则可放入B口:若a[i]大于C ...