文档章节

Go笔记-json

漂泊尘埃
 漂泊尘埃
发布于 2017/02/28 15:01
字数 687
阅读 14
收藏 0

解析json

type Server struct {
	ServerName, ServerIP string
}

type ServerSlice struct {
	Servers []Server
}

func Read() {
	str := `{"servers":[{"serverName":"Shanghai_VPN","serverIP":"127.0.0.1"},{"serverName":"Beijing_VPN","serverIP":"127.0.0.2"}]}`
	var s ServerSlice
	json.Unmarshal([]byte(str), &s)
	fmt.Println(s)
}

输出:

{[{Shanghai_VPN 127.0.0.1} {Beijing_VPN 127.0.0.2}]}

例如JSON的key是Foo,那么怎么找对应的字段呢?

  1. 首先查找tag含有Foo的可导出的struct字段(首字母大写)
  2. 其次查找字段名是Foo的导出字段
  3. 最后查找类似FOO或者FoO这样的除了首字母之外其他大小写不敏感的导出字段,能够被赋值的字段必须是可导出字段(即首字母大写),同时JSON解析的时候只会解析能找得到的字段,找不到的字段会被忽略
  4. json字符串的name可以被解析到Name字段(没有加tag)

遇到的问题

解析到切片

有一个类型是 []*Tree 的字段,如果需要解析到这个字段的话需要使用 &

json.Unmarshal(bytes, &dirData.root.Children)

Children的类型是

Children []*Tree     `json:"children"`

解析到interface

现在我们假设有如下的JSON数据

b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)

如果在我们不知道他的结构的情况下,我们把他解析到interface{}里面

	b := []byte(`{"Name":"Wednesday","Age":6,"Parents":["Gomez","Morticia"]}`)
	var f interface{}
	json.Unmarshal(b, &f) // 这个时候f里面存储了一个map类型,他们的key是string,值存储在空的interface{}里
	if m, ok := f.(map[string]interface{}); ok {
		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 float64:
				fmt.Println(k, "is float64", 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")
			}
		}
	}

生成JSON

结构体定义如上。

	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))

输出:

{"Servers":[{"ServerName":"Shanghai_VPN","ServerIP":"127.0.0.1"},{"ServerName":"Beijing_VPN","ServerIP":"127.0.0.2"}]}

使用json标签

如果将结构体定义成这样:

type Server struct {
	ServerName string `json:"server-name"`
	ServerIP   string `json:"server-ip"`
}

type ServerSlice struct {
	Servers []Server `json:"servers"`
}

输出时:

{"servers":[{"server-name":"Shanghai_VPN","server-ip":"127.0.0.1"},{"server-name":"Beijing_VPN","server-ip":"127.0.0.2"}]}

更多细节参考 json.Marshal

  • 不导出:ID int json:"-"

  • 如果为空,不导出:ServerIP string json:"serverIP,omitempty"

  • 二次JSON编码:

    ServerName  string `json:"serverName"`
    ServerName2 string `json:"serverName2,string"
    

    假如值都是 `Go "1.0" `,输出:

    {"serverName":"Go \"1.0\" ","serverName2":"\"Go \\\"1.0\\\" \""}
    

Unmarshal 中没有的字段不会覆盖成默认值

type User struct {
	Name string
	Age  int
}

func main() {
	u := &User{Name: "chen"}
	err := json.Unmarshal([]byte(`{"Age":18}`), u)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(u) // &{chen 18}
	err = json.Unmarshal([]byte(`{"Name":"hello","Age":18}`), u)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(u) // &{hello 18}
}

自定义解析过程

type DurationConf time.Duration

func (dc *DurationConf) UnmarshalJSON(d []byte) error {
	if len(d) == 0 {
		return errors.New("cann't parse empty string to DurationConf")
	}
	d = bytes.Trim(d, `"`)
	dur, err := time.ParseDuration(string(d))
	if err != nil {
		return err
	}
	*dc = DurationConf(dur)
	return nil
}

注意d中可能会包括双引号。

© 著作权归作者所有

共有 人打赏支持
下一篇: Go笔记-web
漂泊尘埃

漂泊尘埃

粉丝 5
博文 35
码字总数 70992
作品 0
朝阳
私信 提问
译文:笔记本软件 Quiver 简介

英文原文:http://happenapps.com 原文作者:HappenApps, Inc. 中译:不迟any Quiver 程序员的笔记本 Quiver app icon 概述 Quiver 是一款为程序员打造的笔记本。它可以让你方便的在一条笔记...

不迟any
2017/12/10
0
0
go提交json、获取json、解析json

猜你喜欢 Go语言的Json管理模式 golang json string remove field [笔记] Golang JSON go: json解析库go-simplejson使用 Golang 1.6: 数据库NULL值遇到JSON和模板(Template) beego下ie提示下...

d_watson
2016/05/24
43
0
SpringMVC框架 -- json数据交互

一.JSON简单介绍: 参考笔记:JSON简单快速入门 二.json数据交互 请求json 输出json 需要请求数据为json,需要在前端转为json不太方便。不常用 请求key/value、输出json。常用 1.环境搭建 下...

Mr_欢先生
2017/09/28
0
0
Golang学习笔记目录

Golang 介绍 Go语言是谷歌2009发布的第二款开源编程语言。 Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。...

ChainZhang
2017/12/26
0
0
Golang 学习笔记(09)—— json和xml解析

本文为转载,原文:Golang 学习笔记(09)—— json和xml解析 Golang xml package 函数 Marshal Marshal函数返回v的XML编码。 Marshal处理数组或者切片时会序列化每一个元素。Marshal处理指针...

ChainZhang
01/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mariadb二进制包安装,Apache安装

安装mariadb 下载二进制包并解压 [root@test-a src]# wget https://downloads.mariadb.com/MariaDB/mariadb-10.2.6/bintar-linux-glibc_214-x86_64/mariadb-10.2.6-linux-glibc_214-x86_64.t......

野雪球
今天
3
0
ConcurrentHashMap 高并发性的实现机制

ConcurrentHashMap 的结构分析 为了更好的理解 ConcurrentHashMap 高并发的具体实现,让我们先探索它的结构模型。 ConcurrentHashMap 类中包含两个静态内部类 HashEntry 和 Segment。HashEnt...

TonyStarkSir
今天
3
0
大数据教程(7.4)HDFS的java客户端API(流处理方式)

博主上一篇博客分享了namenode和datanode的工作原理,本章节将继前面的HDFS的java客户端简单API后深度讲述HDFS流处理API。 场景:博主前面的文章介绍过HDFS上存的大文件会成不同的块存储在不...

em_aaron
昨天
4
0
聊聊storm的window trigger

序 本文主要研究一下storm的window trigger WindowTridentProcessor.prepare storm-core-1.2.2-sources.jar!/org/apache/storm/trident/windowing/WindowTridentProcessor.java public v......

go4it
昨天
7
0
CentOS 生产环境配置

初始配置 对于一般配置来说,不需要安装 epel-release 仓库,本文主要在于希望跟随 RHEL 的配置流程,紧跟红帽公司对于服务器的配置说明。 # yum update 安装 centos-release-scl # yum ins...

clin003
昨天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部