Lua序列化
我们经常需要序列化一些数据,为了将数据转换为字节流或者字符流,这样我们就可以保存到文件或者通过网络发送出去。我们可以在 Lua 代码中描述序列化的数据,在这种方式下,我们运行读取程序即可从代码中构造出保存的值。
number/string
对于number和string类型其实非常好序列化,number类型就直接返回其本身即可:
if type(o) == "number" thenreturn o
end
string类型需要专门处理,有一个正则匹配是%q,是一种字符串格式化表达式,为了防止类似os.execute('rm *')的注入式攻击,所以采用这种匹配形式来完成string的序列化:
if type(o) == "number" thenreturn string.format("%q",o)
end
若采用类似于("[[", o, "]]")的形式来实现序列化,那么如果输入是" ]]..os.execute('rm *')..[[ ",最后拼接结果则是[[ ]]..os.execute('rm *')..[[ ]],load之后则会出现严重的后果。
table
{["b"] = "Lua",["a"] = 12,["key"] = {["b"] = 4,["a"] = 3,},1 = 2,
}
如果是table类型,如果按照以上形式来呈现序列化效果,则需要注意嵌套table和缩进格式。
function serialize(o,strPrefix)strPrefix = strPrefix or ""if type(o) == "number" thenreturn oelseif type(o) == "string" thenreturn string.format("%q",o)elseif type(o) == "table" thenlocal result = "{\n"for k,v in pairs(o) dolocal strFormat = "%s"if type(k) == "string" thenstrFormat = "[\"%s\"]"endresult = result..strPrefix.."\t"..string.format(strFormat,k).." = "..serialize(v,strPrefix.."\t")..",\n"endresult = result..strPrefix.."}"return resultelse error("cannot serialize a " .. type(o)) end
end
通过pairs循环来对key value值一个个序列化,其中strFormat指的是如果key的类型是string才需要加上【】,以确保正确序列化key值。如果是嵌套table则需要注意递归序列化,传入这个新的table和缩进用以保证正常的序列化输出。于是输入和输出如下:
local tb =
{["a"] = 12, ["b"] = "Lua", [1] = 2,["key"] = {["a"] = 3,["b"] = 4,}
}
print(serialize(tb))
{["b"] = "Lua",["a"] = 12,["key"] = {["b"] = 4,["a"] = 3,},[1] = 2,
}
如果看programming in lua原文,其实大差不差,只是原文没有缩进格式的优化。
循环table
如果出现循环引用table的形式,那么整个问题将会变得比较复杂一点,比如:
local a = {}
a.c = 1
a.z = a
由此可以在之前的基础上做一个优化:缓存table map。意指当我们遍历里面的key值,发现其中仍然有序列化之前已经被序列化的table,则做特殊处理:
local tableMap = {} --用以保存已经被序列化的table
local tbKeyToTableSerialize = {} --用以保存那些引用了table本身的key的序列化stringfunction serialize(o,strPrefix)strPrefix = strPrefix or "" --string前缀,用来正确显示缩进if type(o) == "number" thenreturn oelseif type(o) == "string" thenreturn string.format("%q",o)elseif type(o) == "table" thenlocal result = "{\n"--如果自身是table则第一时间加入表中tableMap[o] = o.namefor k,v in pairs(o) dolocal strFormat = "[%s]"if type(k) == "string" thenstrFormat = "[\"%s\"]"endif type(v) == "table" then--如果是tablemap没有的,则正常序列化,并且存进mapif not tableMap[v] thenresult = result..strPrefix.."\t"..string.format(strFormat,k).." = "..serialize(v,strPrefix.."\t")..",\n"else--否则直接添加到序列化string中,之后直接输出即可table.insert(tbKeyToTableSerialize,o.name.."."..k.." = "..tableMap[v])endelseresult = result..strPrefix.."\t"..string.format(strFormat,k).." = "..serialize(v,strPrefix.."\t")..",\n"endendresult = result..strPrefix.."}"return resultelse error("cannot serialize a " .. type(o)) end
endfunction serializeAll(o)print(o.name.." = "..serialize(o))for i = 1,#tbKeyToTableSerialize doprint(tbKeyToTableSerialize[i])endtbKeyToTableSerialize = {}tableMap = {}
end
最终测试代码和测试结果:
local a = {}
a.name = "a"
a.z = a
a.x = {}
a.x.name = "a.x"
a.x.y = a
a.x.x = a.x
serializeAll(a)
a = {["x"] = {["name"] = "a.x",},["name"] = "a",
}
a.z = a
a.x.y = a
a.x.x = a.x
当然这里的name只是我这边显式添加的value值,实际上可以setmetatable里面复写index来达成条件,但依然是不知道具体table名的。
官方文档相比以上会更激进一些,其直接换成了另一个输出格式:
a = {}
a[1] = {}
a[1][1] = "one"
a[1][2] = "two"
a[2] = 3
b = {}
b["k"] = a[1]
相关文章:
Lua序列化
我们经常需要序列化一些数据,为了将数据转换为字节流或者字符流,这样我们就可以保存到文件或者通过网络发送出去。我们可以在 Lua 代码中描述序列化的数据,在这种方式下,我们运行读取程序即可从代码中构造出保存的值。 number/st…...
Acwing---839. 模拟堆
模拟堆 1.题目2.基本思想3.代码实现 1.题目 维护一个集合,初始时集合为空,支持如下几种操作: I x,插入一个数 x;PM,输出当前集合中的最小值;DM,删除当前集合中的最小值(…...
STM32 STD/HAL库驱动W25Q64模块读写字库数据+OLED0.96显示例程
STM32 STD/HAL库驱动W25Q64 模块读写字库数据OLED0.96显示例程 🎬原创作者对W25Q64保存汉字字库演示: W25Q64保存汉字字库 🎞测试字体显示效果: 📑功能实现说明 利用W25Q64保存汉字字库,OLED显示汉字的时…...
Android 移动应用开发 创建第一个Android项目
文章目录 一、创建第一个Android项目1.1 准备好Android Studio1.2 运行程序1.3 程序结构是什么app下的结构res - 子目录(所有图片、布局、字AndroidManifest.xml 有四大组件,程序添加权限声明 Project下的结构 二、开发android时,部分库下载异…...
MATLAB语音去噪系统
目录 一、背景 二、GUI页面 三、程序 3.1 LMS滤波程序 3.2 GUI程序 四、附录 一、背景 本文介绍了一种最佳的自适应滤波器结构,该结构采用最小均方差(LMS)作为判据,通过不断迭代自适应结构来调整得到最佳滤波器…...
小程序-上传图片功能
技术前置: 1.框架采用colorUI 2.原生开发 功能: 上传图片 1.上传已经拍摄的图片 2.实时拍摄上传 3.设置上传图片数量,每次上传数量 4.上传等待 ChooseImage() {if(this.data.imgList.length>4){_this.ErrorEvent("最多上传4…...
alist基本用法@文档阅读@挂载网盘@网盘webdav挂载
文章目录 alist官网alist网站风格说明alist软件版本 安装和启动使用必看文档👺alist for android版本启动alist网页 典型用例挂载阿里云盘open获取阿里云令牌 主页检查挂载情况 常用页面以配置挂载列表管理配置页面 配置文件和目录👺FAQ可能遇到的错误检…...
Hive正则表达式
Hive版本:hive-3.1.2 一、Hive的正则表达式概述 正则表达式是一种用于匹配和操作文本的强大工具,它是由一系列字符和特殊字符组成的模式,用于描述要匹配的文本模式。 Hive的正则表达式灵活使用解决HQL开发过程中的很多问题,本篇文…...
ubuntu20.04-编译安装Qt5.15.2-C++
文章目录 步骤一:安装依赖项步骤二:下载Qt 5.15源代码步骤三:配置并编译Qt步骤四:配置环境变量注意事项更新于2024年 在Ubuntu 22.04 LTS(Jammy Jellyfish)环境下编译Qt 5.15,由于Ubuntu 22.04的…...
【PTA|期末复习|编程题】数组相关编程题(二)
目录 7-1 数组元素循环右移问题(20分) 输入格式: 输出格式: 输入样例: 输出样例: 代码 7-2 找出不是两个数组共有的元素(20分) 输入格式: 输出格式: 输入样例: 输出样例: 代码 7-3 方阵循环右移(20分) 输入格式: 输出格式: 输入样例&…...
重温阿里云宝塔面板部署前后端项目
首先祝大家新年快乐啊! 回到老家,便打算趁这一段空闲时间提升一下自己,重点是学习实践一下echarts相关内容,很多公司项目都需要实现可视化,所以在bilibili上找了黑马的一个教程开始学习,不同的是ÿ…...
6个好看的wordpress模板
简站wordpress服务业通用主题 2023年立秋纪念版,简站wordpress服务行业通用主题,适合服务行业企业官网使用。 https://www.jianzhanpress.com/?p5393 小语种翻译wordpress主题 小语种国家外贸网站建设需要的wordpress主题模板,适合做小语…...
零基础学python之高级编程(1)---面向对象编程及其类的创建
面向对象编程及其类的创建 文章目录 面向对象编程及其类的创建前言一、面向过程编程和面向对象编程的概念1.面向过程编程(Procedural Programming)2.面向对象编程(Object-Oriented Programming,OOP) 二、面向对象编程基础1.初识类(class)和对象调用方法 2.类中的两种…...
[C# WPF] DataGrid选中行或选中单元格的背景和字体颜色修改
问题描述 WPF中DataGrid的选中行或选中者单元格,在焦点失去后,颜色会很淡,很不明显,不容易区分。 解决方法 在失去焦点的情况下,如何设置行或单元格与选中的时候颜色一样? <DataGrid.Resources>&…...
单片机学习笔记---串口通信(1)
目录 通信的基本概念 通信的方式 1.按照数据传送的方式,可分为串行通信和并行通信。 1.1串行通信 1.2并行通信 2.按照通信的数据同步方式,又可以分为异步通信和同步通信。 2.1 异步通信 2.2同步通信 3.按照数据的传输方向,又可以分为…...
熔断机制解析:如何用Hystrix保障微服务的稳定性
微服务与系统的弹性设计 大家好,我是小黑,在讲Hystrix之前,咱们得先聊聊微服务架构。想象一下,你把一个大型应用拆成一堆小应用,每个都负责一部分功能,这就是微服务。这样做的好处是显而易见的,更新快,容错性强,每个服务可以独立部署,挺美的对吧?但是,问题也随之而…...
第三节 zookeeper基础应用与实战2
目录 1. Watch事件监听 1.1 一次性监听方式:Watcher 1.2 Curator事件监听机制 2. 事务&异步操作演示 2.1 事务演示 2.2 异步操作 3. Zookeeper权限控制 3.1 zk权限控制介绍 3.2 Scheme 权限模式 3.3 ID 授权对象 3.4 Permission权限类型 3.5 在控制台…...
C# Socket通信从入门到精通(21)——Tcp客户端判断与服务器断开连接的三种方法以及C#代码实现
前言 我们开发的tcp客户端程序在连接服务器以后,经常会遇到服务器已经关闭但是作为客户端的我们不知道,这时候应该应该有一个机制我们可以实时监测客户端和服务器已经断开连接,如果已经断开了连接,我们应该及时报警提示用户客户端和服务器已经断开连接,本文介绍三种可以监…...
vulnhub-->hacksudo-Thor靶机详细思路
目录 1. IP探测2.端口服务扫描3.网站漏洞扫描4.目录扫描5.信息分析6.破壳漏洞(Shellshock)nmap---漏洞检测CVE-2014-6271 7.nc反弹8.提权9.service提权 1. IP探测 ┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:10:3c:9b, IPv4: 19…...
Java外卖小程序管理系统
技术架构: springboot ssm mysql redis 有需要该项目的小伙伴可以私信我你的Q。 功能描述: 商品管理:新增商品、所有商品 菜单管理:菜单管理、菜单分类 订单管理:订单总览(包括未付款、已付款、已…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
渲染学进阶内容——模型
最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
MySQL JOIN 表过多的优化思路
当 MySQL 查询涉及大量表 JOIN 时,性能会显著下降。以下是优化思路和简易实现方法: 一、核心优化思路 减少 JOIN 数量 数据冗余:添加必要的冗余字段(如订单表直接存储用户名)合并表:将频繁关联的小表合并成…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
LRU 缓存机制详解与实现(Java版) + 力扣解决
📌 LRU 缓存机制详解与实现(Java版) 一、📖 问题背景 在日常开发中,我们经常会使用 缓存(Cache) 来提升性能。但由于内存有限,缓存不可能无限增长,于是需要策略决定&am…...
