我爱编程

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

2018-01-05  本文已影响0人  小歪子go

一、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

上一篇 下一篇

猜你喜欢

热点阅读