热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

json解析:marshal和unmarshal

Go使用encodingjson包的marshal和unmarshal实现json数据的编解码。分别记录如下:1.marshal定义结构体:typeOCPstruct{Names


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] }

从输出可以看出:



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




推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
  • 如何查询zone下的表的信息
    本文介绍了如何通过TcaplusDB知识库查询zone下的表的信息。包括请求地址、GET请求参数说明、返回参数说明等内容。通过curl方法发起请求,并提供了请求示例。 ... [详细]
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
  • Day2列表、字典、集合操作详解
    本文详细介绍了列表、字典、集合的操作方法,包括定义列表、访问列表元素、字符串操作、字典操作、集合操作、文件操作、字符编码与转码等内容。内容详实,适合初学者参考。 ... [详细]
author-avatar
星痕之刃
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有