Go语言开发中Json、Xml数据的编码和解析

一、Json数据的解析和编码

在开发过程中我们常常需要对数据进行编码和解析
import "encoding/json"
这个包包实现了json对象的编解码,参见RFC 4627。Json对象和go类型的映射关系请参见Marshal和Unmarshal函数的文档。可在官方文档上面参考官方文档

1)json解析

package main

import (
    "encoding/json"
    "fmt"
)

type Student struct {
    ID     int
    Name   string
    Sex    string
    Course []string
}

func main() {
    EncodeStruct()
    DecodeJsonString()
}

//将一个对象编码成json字符串
func EncodeStruct() {
    student := Student{
        ID:     14343466,
        Name:   "wangbiao",
        Sex:    "M",
        Course: []string{"English", "Math", "Chinese"},
    }
    b, err := json.Marshal(student)
    if err != nil {
        fmt.Println("error:", err)
    }
    fmt.Println(string(b))
}


//将json字符串解码成json字符串
func DecodeJsonString() {
    var jsonBody = []byte(`{"ID":14343466,"Name":"wangbiao","Sex":"M","Course":["English","Math","Chinese"]}`)
    var student1 = Student{}
    err := json.Unmarshal(jsonBody, &student1)
    if err != nil {
        fmt.Println(err.Error())
        return
    }
    fmt.Println(student1)
    fmt.Println("studentName:", student1.Name)
    fmt.Println("studentId:", student1.ID)
    fmt.Println("studentSex:", student1.Sex)
    fmt.Println("studentCourse:", student1.Course)
}

2)json生成

针对JSON的输出,我们在定义struct tag的时候需要注意的几点是:
字段的tag是"-",那么这个字段不会输出到JSON
tag中带有自定义名称,那么这个自定义名称会出现在JSON的字段名中,例如上面例子中serverName
tag中如果带有"omitempty"选项,那么如果该字段值为空,就不会输出到JSON串中
如果字段类型是bool, string, int, int64等,而tag中带有",string"选项,那么这个字段在输出到JSON的时候会把该字段对应的值转换成JSON字符串

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"`
}

s := Server {
    ID:         3,
    ServerName:  `Go "1.0" `,
    ServerName2: `Go "1.0" `,
    ServerIP:   ``,
}
b, _ := json.Marshal(s)
os.Stdout.Write(b)

在涉及到orm时候tag
type studentinfo struct {
    Id          int    `pk:"auto"`
    Stuname     string `orm:"size(20)"`
    Stuidentify string `orm:"size(30)"`
    Stubirth    time.Time
    Stuclass    string `orm:"size(30)"`
    Stumajor    string `orm:"size(30)"`
}

output:{"serverName":"Go "1.0" ","serverName2":""Go \"1.0\" ""}
输出结果如下图:


效果图

二、Xml数据解析和编码

现在大多数数据交互都是json,但是有些和第三方公司对接还是喜欢以Xml进行数据交互,例如美团和微信第三方sdk的服务端数据交互即使以xml进行的,因此了解Xml的生成和解析也是很有必要的
xml解析基本遵循以下原则:
如果v是 array或者slice,那么输出每一个元素,类似value
如果v是指针,那么会Marshal指针指向的内容,如果指针为空,什么都不输出
如果v是interface,那么就处理interface所包含的数据
如果v是其他数据类型,就会输出这个数据类型所拥有的字段信息
生成的XML文件中的element的名字又是根据什么决定的呢?元素名按照如下优先级从struct中获取:

如果v是struct,XMLName的tag中定义的名称
类型为xml.Name的名叫XMLName的字段的值
通过struct中字段的tag来获取
通过struct的字段名用来获取
marshall的类型名称
我们应如何设置struct 中字段的tag信息以控制最终xml文件的生成呢?

XMLName不会被输出
tag中含有"-"的字段不会输出
tag中含有"name,attr",会以name作为属性名,字段值作为值输出为这个XML元素的属性,如上version字段所描述
tag中含有",attr",会以这个struct的字段名作为属性名输出为XML元素的属性,类似上一条,只是这个name默认是字段名了。
tag中含有",chardata",输出为xml的 character data而非element。
tag中含有",innerxml",将会被原样输出,而不会进行常规的编码过程
tag中含有",comment",将被当作xml注释来输出,而不会进行常规的编码过程,字段值中不能含有"--"字符串
tag中含有"omitempty",如果该字段的值为空值那么该字段就不会被输出到XML,空值包括:false、0、nil指针或nil接口,任何长度为0的array, slice, map或者string
tag中含有"a>b>c",那么就会循环输出三个元素a包含b,b包含c,例如如下代码就会输出

1)xml解析:

type Students struct {
    XMLName xml.Name  `xml:"students"`
    Version string    `xml:"version,attr"`
    Stus    []Student `xml:"student"`
}
type Student struct {
    StudentID int    `xml:"studentid"`
    Name      string `xml:"studentname"`
    Address   string `xml:"address"`
    School    string `xml:"school"`
    Age       int    `xml:"age"`
    Sex       int    `xml:"sex"`
}
func CreateStudentXml() {
    stus := &Students{}
    stus.Version = "1"
    stus.Stus = append(stus.Stus, Student{
        StudentID: 3782378,
        Name:      "江华",
        Address:   "zhongguo guangzhou",
        School:    "TaiAn Schlool",
        Age:       34,
        Sex:       0,
    })
    stus.Stus = append(stus.Stus, Student{
        StudentID: 3782379,
        Name:      "小歪子Go",
        Address:   "zhongguo guangzhou",
        School:    "ShiPai Schlool",
        Age:       30,
        Sex:       1,
    })
    out, err := xml.MarshalIndent(stus, "", "")
    if err != nil {
        fmt.Printf("error:%v\n", err)
    } else {
        // os.Stdout.Write([]byte(xml.Header))
        // os.Stdout.Write(out)
        fmt.Println("xxp")
        fmt.Println(`<?xml version="1.0" encoding="UTF-8"?>` + "\n" + string(out))
    }
}

output:
<?xml version="1.0" encoding="utf-8"?>

<students version="1">
<student>
<studentid>3782378</studentid>
<studentname>江华</studentname>
<address>zhongguo guangzhou</address>
<school>TaiAn Schlool</school>
<age>34</age>
<sex>0</sex>
</student>
<student>
<studentid>3782379</studentid>
<studentname>小歪子Go</studentname>
<address>zhongguo guangzhou</address>
<school>ShiPai Schlool</school>
<age>30</age>
<sex>1</sex>
</student>
</students>

2)xml解析成student

func CreatStudentFromXml() {
    stus := Students{}
    datas := []byte(string(`<?xml version="1.0" encoding="UTF-8"?>
    <students version="1"><student><studentid>3782378</studentid><studentname>江华</studentname><address>zhongguo guangzhou</address><school>TaiAn Schlool</school><age>34</age><sex>0</sex></student><student><studentid>3782379</studentid><studentname>小歪子Go</studentname><address>zhongguo guangzhou</address><school>ShiPai Schlool</school><age>30</age><sex>1</sex></student></students>
`))
    err := xml.Unmarshal(datas, &stus)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(stus)
    }

}

output:{{ students} 1 [{3782378 江华 zhongguo guangzhou TaiAn Schlool 34 0} {3782379 小歪子Go zhongguo guangzhou ShiPai Schlool 30 1}]}
参考文档
在Go语言中使用JSON

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,596评论 18 139
  • JSON JSON和XML都是需要解析的 JSON是一种轻量级的数据格式,一般用于数据交互服务器返回给客户端的数据...
    JonesCxy阅读 1,842评论 2 10
  • 本周帮同事做一个测试用的工具,一个模拟的服务器,根据请求中的用户ID从数据库中查找预先设置好的响应返回给客户端。前...
    FunFeast阅读 411评论 0 7
  • Go入门 Go介绍 部落图鉴之Go:爹好还这么努力? 环境配置 安装 下载源码编译安装 下载相应平台的安装包安装 ...
    齐天大圣李圣杰阅读 4,567评论 0 26
  • Swift版本点击这里欢迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh阅读 25,280评论 7 249