小工具      在线工具  汉语词典  css  js  c++  java

序列化与反序列化

Code Tools,java,golang 额外说明

收录于:152天前

JSON
JSON是一种轻量级的数据交换格式,易于编写也易于机器解析和生成。

JSON格式可以有效提高网络传输效率。在传输过程中,可以将程序中的数据类型序列化为json字符串,在接收端通过反序列化恢复原来的数据格式。

序列化
网络传输
反序列化
程序
JSON 字符串
程序
其他语言

在这里插入图片描述

JSON是一种键值对格式,如下:

{
    
	"name":"小许",
	"sex" : "男",
	"age" : 18,
	"address":["北京","天津","河北"]
}

JSON格式简单、传输速度快,是数据传输的主要格式。基本上,编程语言都支持将编程语言中内置结构的数据转换为json字符串。

序列化

在不同语言中有不同的方式,下面将介绍Java与Go语言的序列化与反序列化。在Java中一切皆对象,所以序列化非常容易,直接继承java.io.Serializable。一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据的类型。

public class Person implements java.io.Serializable{
    
	private int id;
	private String name;
	private String sex;
	private String address;
	
	/** 省略setter和getter */
}

继承对象后,可以调用以下函数来序列化Java对象

public final void writeObject(Object x) throws IOException

并通过以下函数反序列化

public final Object readObject() throws IOException, ClassNotFoundException

Go语言对JSON操作的包均在encoding/json包下,包下提供了Marshal方法来序列化Go内置对象。Marshal函数返回v的json编码。

func Marshal(v interface{}) ([]byte, error)

//创建结构体
type Person struct {
    
	name    string
	address string
}


//序列化
per := Person{
    
	name:    "钢铁侠",
	address: "漫威",
}
perjson, err := json.Marshal(&per)
if err != nil {
    
	panic(err)
}
fmt.Printf("per序列化的json数据为为:%v", perjson)
fmt.Printf("per序列化的json字符串为:%v", string(perjson))

在这里插入图片描述

上面的代码中序列化了一个Person对象,但是打印时打印失败。这是因为结构体成员都是小写的,只能在这个包内访问。序列化没有意义,不支持私有类的序列化。

type Person struct {
    
	Name    string
	Address string
}

将结构体改为公共类时就可以序列化了。
在这里插入图片描述

与 Java 万物皆对象的本质不同,Go 除了结构体之外,还有映射、数组、切片等。

//定义一个map类型
func initMap() map[string]string {
    
	var tmp map[string]string = map[string]string{
    }
	tmp["1"] = "aaa"
	tmp["2"] = "bbb"
	tmp["3"] = "ccc"
	return tmp
}

//对map序列化
a := initMap()

ajson, err := json.Marshal(&a)
if err != nil {
    
	panic("ajson序列化失败")
}
fmt.Printf("%v\n", ajson)
fmt.Println(string(ajson))


在这里插入图片描述

//输出序列化时的数据类型
fmt.Printf("%T\n", ajson)
fmt.Printf("%T\n", string(ajson))

在这里插入图片描述
可以看出序列化后时一个字节数组,通过string()函数将其转化为字符串,即为json字符串。

Go序列化时tag标签的使用

序列化时,成员变量的名称全部大写。但在实际使用中,需要统一的书写标准和具体的名称,这就需要在序列化时使用标签。

{
    "Name":"钢铁侠","Address":"漫威"}

Go语言结构体序列化tag使用规则是在结构体字段后添加json:"name"并用反引号包裹。

type Person struct {
    
	Name    string `json:"person_name"`
	Address string `json:"person_address"`
	Age     int
}

如果在“名称”和“地址”中使用标签,它们的序列化名称将成为自定义的 person_names。 Age成员不使用标签,因此不会改变。

per := Person{
    
	Name:    "钢铁侠",
	Address: "漫威",
	Age:     18,
}
perjson, err := json.Marshal(&per)
if err != nil {
    
	panic(err)
}
fmt.Printf("per序列化的json数据为为:%v", perjson)
fmt.Printf("per序列化的json字符串为:%v", string(perjson))

在这里插入图片描述
struct的tag只会在序列化时起作用不会影响结构体的使用。

反序列化

反序列化就是将序列化后的json字符串或者字节数组转换成编程语言内置的数据结构。这种反序列化可以在相同语言或不同语言中发生。例如Java类被序列化并通过网络传输到前端进行json反序列化,或者任何其他后端语言将内置数据序列化并传输。到前端。

反序列化序列化数据的语言相同,Java实现和Go实现。

/** go语言实现 */

//定义结构体
type Person struct {
    
	Name    string `json:"person_name"`
	Address string `json:"person_address"`
	Age     int    `json:"person_age"`
}

//序列化
per := Person{
    
	Name:    "钢铁侠",
	Address: "漫威",
	Age:     18,
}
perjson, err := json.Marshal(&per)
if err != nil {
    
	panic(err)
}
fmt.Printf("per序列化的json数据为为:%v", perjson)
fmt.Printf("per序列化的json字符串为:%v", string(perjson))

在这里插入图片描述
序列化后为一个字节数组,可以通过string()方法转化为字符串。

func json.Unmarshal(data []byte, v any) error
该方法时反序列化方法,第一个参数为需要反序列化的字节数组,第二个参数为反序列化后数据的赋值变量。

//反序列化赋值变量
var per1 Person
err1 := json.Unmarshal(perjson, &per1)
if err1 != nil {
    
	panic(err1)
}
fmt.Printf("反序列化的数据per1%s,%s,%d", per1.Name, per1.Address, per1.Age)

在这里插入图片描述

str := `{"person_name":"钢铁侠","person_address":"漫威","person_age":18}`

var per2 Person
err2 := json.Unmarshal([]byte(str), &per2)
if err2 != nil {
    
	panic(err2)
}
fmt.Println(per2)

对字符串也可以反序列化,需要将字符串转化为字节数组,通过[]byte()方法。

/** Java实现 */

//定义类实现序列化接口java.io.Serializable
public class Person implements java.io.Serializable
{
    
   public String name;
   public String address;
   public int id;
   /* getter setter toString ... */
}

//实例化类并序列化类
Person per = new Person();
per.name = "小许";
per.address = "中国";
per.id = 111111;

FileOutputStream fs = new FileOutputStream("./tmp/per.txt");
ObjectOutputStream out = new ObjectOutputStream(fs);
out.writeObject(e);
out.close();
fs.close();
System.out.printf("data is saved in ./tmp/per.txt");


//反序列化
Person e = null;
FileInputStream fileIn = new FileInputStream("./tmp/Person.txt");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Person) in.readObject();
in.close();
fileIn.close();
System.out.println("反序列化的对象",e);
System.out.println("name: " + e.name);
System.out.println("address: " + e.address);
System.out.println("id: " + e.id);

这个序列化的字节数组直接存储在文件中。一般情况下是直接通过http协议等网络传输到浏览器,由浏览器内置的解析器,即js进行反序列化。

在前后端交互的过程中主要的数据传输方式就是json字符串串,一般将后端语言的内置对象及数据结构都序列化为json字符串,再由Javascript的JSON,parse()方法将json字符串转化为js的内置对象。

JS中内置了json字符串与json数据的转化方法,因此只需要再后端语言中将内置数据序列化为json字符串即可,这个过程是统一的,因此诞生了很多序列化工具,仅需少量的代码即可序列化,如阿里巴巴的fastjson,apache的jackson等。

. . .

相关推荐

额外说明

使用Access时遇到的问题

问题一:[Microsoft][ODBC 驱动程序管理器] 在指定的 DSN 中,驱动程序和应用程序之间的体系结构不匹配 一看到这个dns,就知道跟ODBC数据源有关系。但是我这里安装了Access驱动,配置了ODBC数据源,为什么还报错呢?就这问题,折

额外说明

校园招聘经验分享——我本科如何进大厂

写在开头   最近签完了三方,大学前三年的生涯规划和努力最终还是得到了兑现,脑子里不断涌现这几年来的经历,一直想着写点什么东西记录一下,刚好大四空闲时间真的太多,心血来潮,不如还是写写吧,记录一下我这三年向目标前进走过的路。   同时,无论是在学校、实习

额外说明

[Eigen中文文档] 在 CMake 项目中使用 Eigen

文档总目录 英文原文(Using Eigen in CMake Projects) Eigen提供了CMake支持,使得该库可以轻松地在CMake项目中使用。 注意:启用这个功能需要CMake 3.0(或更高版本)。 Eigen提供了一个CMake示例,

额外说明

2017年美国大学生数学建模竞赛E题O奖65123论文解读

论文PDF:E2017年美国大学生数学建模竞赛O奖论文全部65123-校苑数模_人人文库网 Summary Finally 我们分析了所提出方法的优缺点 该研究也可以满足ICM的需要,为城市设计提供合理的增长理论(题目中说:ICM需要你帮助他们实施智能化

额外说明

neutron服务启动源码分析(二)

在上文中我们分析了neutron server的启动流程,其中有一步被我标红了,就是 通过paster.deploy 创建了neutron的app, paster.deploy 做了哪些事情呢 neutron/service.py def _run_ws

额外说明

CSS学习 1.增加字体和颜色样式

CSS学习 1.增加字体和颜色样式 设置文本样式 字体系列 body { font-family: Verdana, Geneva, Arial, sans-serif(通用字体系列名); } 字体大小 body { font-size: 14px; }

额外说明

【Python 随练】编写一个程序,将两个字符串进行连接

题目: 编写一个程序,将两个字符串进行连接。 简介: 在本篇博客中,我们将介绍如何使用Python编写一个简单的字符串连接程序。我们将讨论不同的方法,并提供完整的代码示例。 问题分析: 给定两个字符串,我们需要将它们连接在一起形成一个新的字符串。 解决方

额外说明

python 内置函数

内置函数的使用: 1、eval()函数:对动态表达式进行求值。 x=2 str='x**2+2*x+9' print(eval(str)) //将字符串生成语句执行。 17 2、exec()函数:执行动态语句;不返回值。 exec("for

额外说明

MySql之主从复制

MySql之主从复制 什么是MYSQL的主从复制 主从复制是指将一个服务器作为主服务器,所有的数据更新操作都在主服务器进行,并且将主服务器的数据同步到一个或多个从服务器,保证从服务器和主服务器的数据一致。 为什么需要主从复制 高可用,主从复制实现了数据的

额外说明

MinIO【部署 01】MinIO安装及SpringBoot集成简单测试

MinIO安装及SpringBoot集成测试 1.下载安装 1.1 Install the MinIO Server 1.2 Launch the MinIO Server 1.3 Connect Your Browser to the MinIO Se

ads via 小工具