使用lua-cmsgpack序列化和反序列化lua对象
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用lua-cmsgpack序列化和反序列化lua对象相关的知识,希望对你有一定的参考价值。
参考技术A lua-cmsgpack是一个开源的MessagePack实现方式、纯C的库,没有任何其它依赖,编译后可以直接被lua调用,目前主要支持Lua 5.1/5.2/5.3 版本。1、什么是MessagePack?
官方的解释是:
跟JSON及其类似,但是比JSON更快并且占用空间更小,举个官方给出的例子,直接截官方图:
翻译官方的解释:
MessagePack是一种高效的二进制序列化格式, 它允许在多种语言(如JSON)之间交换数据,但它越来越小, 小整数被编码为单个字节,典型的短字符串除了字符串本身之外还需要一个额外的字节。
目前市面上流行的开发语言MessagePack几乎支持,官方的地址为: http://msgpack.org/Lua MessagePack也提供了一套开源库,地址在: https://github.com/fperrad/lua-MessagePack/ 。
但是,作者使用的是lua-cmsgpack,至于哪个比较优异,作者还没有去比较,主要是先发现了lua-cmsgpack,后面看了下README文件,使用方法应该是差不多的,大家可以拿来参考。
lua-cmsgpack包括官方提供的lua-MessagePack都需要自行编译,因为可能平台太多,所以官方没有为每一个平台提供编译好的版本。lua-cmsgpack的github地址为: https://github.com/antirez/lua-cmsgpack
git clone下来之后需要安装cmake工具,mac平台直接在项目目录:
即可,当然需要预先安装lua,并且是5.1版本以上的。
主要说下CentOS平台下cmake可能会出现的问题,如果cmake的过程出现以下错误:
出现以上错误的话,需要自行安装lua的一些依赖库,一般:
就可以了,如果还不行,再试试下面的命令:
编译完成之后会生成cmsgpack.so文件,使用的时候直接require进去即可
运行效果:
cmsgpack.pack()可以把多个lua对象序列化成一个二进制msgpack,执行反序化的时候会返回对应数量的lua对象,非常的方便。
有趣的是redis也支持MessagePack,因此结合lua和lua-cmsgpack可以产生不错的化学反应,下面是一个简单的例子(结合OpenResty):
测试返回结果:
在某些场合还是有不错应用场景的。
使用和反序列化 FileStreamResult Blazor
【中文标题】使用和反序列化 FileStreamResult Blazor【英文标题】:Consume and Deserialize FileStreamResult Blazor 【发布时间】:2020-10-31 06:38:04 【问题描述】:我有一个控制器端点,它提供如下文件;
[HttpGet]
[ProducesResponseType(typeof(FileStreamResult), 200)]
[Route("documentId")]
public IActionResult GetDocumentImage(int documentId)
var response = _service.Get(documentId);
HttpAssert.Success(response);
HttpAssert.IsNotNull(response);
Stream stream = new MemoryStream(response.Result.Data);
if (stream == null)
return NotFound();
return File(stream, response.Result.MimeType);
当在img
标签上设置为src
时效果很好,并且可以确认文件正在成功发送。
我想在 blazor
razor
页面中使用结果。我使用
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
var result = JsonConvert.DeserializeObject<T>(responseContent);
return new ServiceResponse<T> Result = result, HasError = false, HttpErrorCode = -1, Error = null ;
但是,当我反序列化为object
(使用JsonConvert.DeserializeObject<T>(responseContent)
)时
当我调试并尝试在我得到的监视窗口中进行评估时,抛出没有 ex.Message
的错误
'解析值时遇到意外字符:%。路径'',第 0 行,位置 0。'
这种情况下的返回是一个 PDF 文件。谁能指导我哪里出错了?
【问题讨论】:
【参考方案1】:正如 TomTom 所说,您不能将 PDF 转换为 json,PDF 不像文本或 json 文件。
所以在 Blazor 中,您必须按照以下方式进行操作。
当您从端点取回结果时,它将是一个流。因此,您可以执行以下操作来获取stream from the endpoint:
var fileStream = new FileStream()
Stream = await httpResponseMessage.Content.ReadAsStreamAsync(),
Filename = $"someFile.pdf"
;
获取文件流后,你必须convert it to byte:
byte[] bytes;
using (var memoryStream = new System.IO.MemoryStream())
fileStream.Stream.CopyTo(memoryStream);
bytes = memoryStream.ToArray();
一旦你将它保存在字节数组中,它现在是数组格式,我们现在可以通过用户浏览器使用和下载它。您必须创建以下 js 以触发 Blazor 中的浏览器下载
这里我们基本上是在 HTML DOM 中创建一个锚点并触发一个点击事件(source):
var saveAsFile = function (filename, bytesBase64)
var link = document.createElement('a');
link.download = filename;
link.href = "data:application/octet-stream;base64," + bytesBase64;
document.body.appendChild(link); // Needed for Firefox
link.click();
document.body.removeChild(link);
我们可以在 Blazor c# 代码中调用下面的代码并通过JSInterop 触发它
await JsRunTime.InvokeAsync<object>("saveAsFile", fileStream.Filename,
Convert.ToBase64String(bytes));
【讨论】:
【参考方案2】:啊,指出了明显的问题,但你已经告诉我们错了:
这种情况下的返回是一个PDF文件。
看,PDF 文件不是 JSON。
您尝试使用 JSON 转换器反序列化 PDF 文件:
var 结果 = JsonConvert.DeserializeObject(responseContent);
我不确定你从哪里得到这应该起作用的想法。 PDF 不是 JSON。哎呀,甚至“ReadAsStringAsync()”可能没有任何意义——我什至不确定 PDF 是否完全异步。它绝对不是 JSON。
【讨论】:
谢谢你,令人担忧的是我从来没有想过。那么我将如何将FileStreamResult
反序列化为对象甚至byte[]
?
从文档开始。我的意思是,您找到了 ReadAsString - 通过所有扩展方法找到将流作为字节数组读取的方法应该很简单。内容是一个流。流到字节数组 - 你基本上要求我为你阅读文档。永远不要那样做。【参考方案3】:
类似于Umair's answer,您可以这样做,而不是创建一个新的 FileStream 和一个新的 MemoryStream:
using var streamReader = new StreamReader(await httpResponseMessage.Content.ReadAsStreamAsync());
var fileString = await streamReader.ReadToEndAsync();
var bytes = Encoding.ASCII.GetBytes(fileString);
然后还是按照 Umair 的示例 JS Blazor 触发代码调用 saveFileAs 和 InvokeAsync。
【讨论】:
以上是关于使用lua-cmsgpack序列化和反序列化lua对象的主要内容,如果未能解决你的问题,请参考以下文章