Go 使用 encoding/json 包的 marshal 和 unmarshal 实现 json 数据的编解码。分别记录如下:

1. marshal

定义结构体:

type OCP struct {
Name string `json:"name"`
ImageRegistry *ImageRegistry `json:"imageRegistry"`
Status string `json:"status"`
Events []string `json:"events"`
id *int
} type ImageRegistry struct {
Addr string `json:"addr"`
User string `json:"user"`
Password string `json:"password"`
}

将结构体 OCP 类型值编码成 json 格式:

func main() {
imageRegistry := ImageRegistry{
Addr: "x.x.x.x",
User: "admin",
Password: "admin",
} ocp := OCP{
Name: "lubanseven",
ImageRegistry: &imageRegistry,
Status: "running",
Events: []string{"normal", "normal", "normal"},
} data, err := json.Marshal(ocp)
if err != nil {
fmt.Println(err)
} fmt.Println(string(data))
}

输出:

{"name":"lubanseven","imageRegistry":{"addr":"x.x.x.x","user":"admin","password":"admin"},"status":"running","events":["normal","normal","normal"]}

从输出可以看出:

  1. 结构体中以小写字母开头的类型(id)不会被编码。
  2. 结构体中指针类型在编码时将转换为指针所指向的值。

更多编码规则可看 JSON and Go

2. unmarshal

类似的将 data 解码为结构体类型 OCP 的值:

var lubanseven OCP
err = json.Unmarshal(data, &lubanseven)
if err != nil {
fmt.Println(err)
}
fmt.Println(lubanseven)

输出:

{lubanseven 0xc00020e360 running [normal normal normal] <nil>}

从输出可以看出:

  1. 指针类型的值在解码时将转换为值的地址。
  2. 对于无法解码的值,将转换为该值的零值,如指针类型变量 id 解码为 nil。

更多编码规则可看 JSON and Go

对于第二点,将 id 类型定义成 int,查看解码后的结构体值:

type OCP struct {
Name string `json:"name"`
ImageRegistry *ImageRegistry `json:"imageRegistry"`
Status string `json:"status"`
Events []string `json:"events"`
id int
}

输出:

{lubanseven 0xc0000cc4b0 running [normal normal normal] 0}

这点在解码的时候要注意。

上例中解码的结构体类型是已知的,如果结构体未知该如何确定结构体类型呢?这在实际场景中是会发生的,比如传输的数据流,事先不知道其结构体类型。

可以通过类型断言的方式,确定结构体类型,如下:

var lubanunknown interface{}
err = json.Unmarshal(data, &lubanunknown)
if err != nil {
fmt.Println(err)
}
fmt.Println(lubanunknown) if value, ok := lubanunknown.(map[string]interface{}); ok {
fmt.Println(value)
}

输出:

map[events:[normal normal normal] imageRegistry:map[addr:x.x.x.x password:admin user:admin] name:lubanseven status:running]
map[events:[normal normal normal] imageRegistry:map[addr:x.x.x.x password:admin user:admin] name:lubanseven status:running]

输出类型是 map[string]interface{},key 是 string,value 是 interface{},可以对 value 进行类型断言确定 interface{} 的实质类型(直接看输出也能看出来...):

value := lubanunknown.(map[string]interface{})

for k, v := range value {
switch vv := v.(type) {
case int:
fmt.Println(k, "is int: ", vv)
case string:
fmt.Println(k, "is string: ", vv)
case []interface{}:
fmt.Println(k, "is slice: ", vv)
for _, v := range vv {
fmt.Println(v)
}
case map[string]interface{}:
fmt.Println(k, "is struct: ", vv)
default:
fmt.Println(k, "unexpect type of ", reflect.TypeOf(vv))
}
}

输出:

imageRegistry is struct:  map[addr:x.x.x.x password:admin user:admin]
status is string: running
events is slice: [normal normal normal]
normal
normal
normal
name is string: lubanseven

3. 数据流的 json 编解码

对数据流的编解码,如下:

package main

import (
"encoding/json"
"log"
"os"
) func main() {
dec := json.NewDecoder(os.Stdin)
enc := json.NewEncoder(os.Stdout)
for {
var v map[string]interface{}
if err := dec.Decode(&v); err != nil {
log.Println(err)
return
}
for k := range v {
if k != "Name" {
delete(v, k)
}
}
if err := enc.Encode(&v); err != nil {
log.Println(err)
}
}
}

示例来自 JSON and Go

运行示例:

$ go run main.go
{"name":"lubanseven","imageRegistry":{"addr":"x.x.x.x","user":"admin","password":"admin"},"status":"running","events":["normal","normal","normal"]}
{}
{"Name":"lubanseven","imageRegistry":{"addr":"x.x.x.x","user":"admin","password":"admin"},"status":"running","events":["normal","normal","normal"]}
{"Name":"lubanseven"}

json 解析:marshal 和 unmarshal的更多相关文章

  1. go json解析Marshal和Unmarshal

    Decoder: package main import ( "encoding/json" "fmt" "io" "log&qu ...

  2. golang struct 定义中json``解析说明

    在代码学习过程中,发现struct定义中可以包含`json:"name"`的声明,所以在网上找了一些资料研究了一下 package main import ( "enco ...

  3. go语言之进阶篇json解析到map

    1.json解析到map(通过类型断言,找到值和value类型) 示例: package main import ( "encoding/json" "fmt" ...

  4. go语言之进阶篇json解析到结构体

    1.json解析到结构体 示例: package main import ( "encoding/json" "fmt" ) type IT struct { ...

  5. [GO]json解析到map

    package main import ( "encoding/json" "fmt" ) var str string func main() { m := ...

  6. 深入 Go 中各个高性能 JSON 解析库

    转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com/archives/535 其实本来我是没打算去看 JSON 库的性能问题的,但是最近我对 ...

  7. 【golang】json数据解析 - 嵌套json解析

    @ 目录 1. 通过结构体映射解析 2. 嵌套json解析-map 1. 通过结构体映射解析 原数据结构 解析 // 结构体 type contractJson struct { Data []tra ...

  8. Android okHttp网络请求之Json解析

    前言: 前面两篇文章介绍了基于okHttp的post.get请求,以及文件的上传下载,今天主要介绍一下如何和Json解析一起使用?如何才能提高开发效率? okHttp相关文章地址: Android o ...

  9. Json解析工具的选择

    前言 前段时间@寒江不钓同学针对国内Top500和Google Play Top200 Android应用做了全面的分析(具体分析报告见文末的参考资料),其中有涉及到对主流应用使用json框架Gson ...

  10. iOS json 解析遇到error: Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed.

    Error Domain=NSCocoaErrorDomain Code=3840 "The operation couldn’t be completed. (Cocoa error 38 ...

随机推荐

  1. MybatisPlus的一些高级特性

    1.MybatisPlus多数据源配合 导入相关依赖 <dependency> <groupId>com.baomidou</groupId> <artifa ...

  2. 手动安装pinia、给项目添加pinia实例

    用你喜欢的js包管理器安装pinia: yarn add pinia # 或者使用 npm npm install pinia 创建一个 pinia 实例 (根 store) 并将其传递给应用: 编辑 ...

  3. RIPEMD加密算法:原理、应用与安全性

    一.引言 在信息时代,数据安全愈发受到重视,加密算法作为保障信息安全的关键技术,其性能和安全性备受关注.RIPEMD(RACE Integrity Primitives Evaluation Mess ...

  4. 【C++】【图像处理】形态学处理(腐蚀、膨胀)算法解析(以.raw格式的图像为基础进行图像处理、gray levels:256)

    1 void erosion(BYTE* image, int w, int h, BYTE* outImg) 2 { 3 int rept; 4 //腐蚀 5 memcpy(outImg, imag ...

  5. 【C#】【System.IO】关于拷贝文件夹以及(Directory和DirectoryInfo、File和FileInfo)的区别

    本次问题是想要拷贝文件夹,但是找了一圈发现只有File有Copy或者FileInfo的CopyTo,并没有Directory的拷贝操作方法. 针对C#中拷贝文件夹的方法就是先生成一个目标文件夹(des ...

  6. DVWA Brute Force(暴力破解)全等级

    Brute Force(暴力破解) 目录: Brute Force(暴力破解) 1.Low 2.Medium 3.High 方法1--Burp爆破 方法2--Python脚本爆破 4.Impossib ...

  7. 一文读懂Spring框架中依赖注入流程

    想读懂Spring的依赖注入流程,我们先简单了解一下Ioc和DI是什么? IoC和DI Ioc-Inversion of Control,即"控制反转",不是什么技术,而是一种设计 ...

  8. VSCode 终端选择文本自动复制

    Ctrl + , 打开设置 搜索 copyOnSelection,勾选即可 对应的 settings.json 如下 "terminal.integrated.copyOnSelection ...

  9. 【华为云技术分享】40%性能提升,华为云推出PostgreSQL 12 商用版

    摘要:日前,华为云数据库正式推出了RDS for PostgreSQL 12版本,并开始商用.本文将从华为云RDS for PostgreSQL 12的4大特性和架构图等多方面来解读华为云Postgr ...

  10. 视频编码耗时长、编码帧发送失败…DVPP视频编码问题典型案例分析

    摘要:本期就分享几个关于DVPP视频编码问题的典型案例,并给出原因分析及解决方法 本文分享自华为云社区<DVPP媒体数据处理视频编码问题案例>,作者:昇腾CANN. DVPP(Digita ...