# ohos_avro **Repository Path**: codeeeeeee/ohos_avro ## Basic Information - **Project Name**: ohos_avro - **Description**: avro的c库鸿蒙化适配 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2025-08-04 - **Last Updated**: 2025-09-30 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # avro ## 简介 > 本软件是参照开源软件[apache avro](https://github.com/apache/avro)源码适配OpenHarmony实现的数据序列化系统,支持丰富的数据结构,将其转化成便于存储或传输的二进制数据格式。它同时也是一个容器文件,用于存储持久数据。 ## 效果展示: ## 下载安装 ```` ohpm install @ohos/avro ```` OpenHarmony ohpm 环境配置等更多内容,请参考[如何安装 OpenHarmony ohpm 包](https://gitcode.com/openharmony-tpc/docs/blob/master/OpenHarmony_har_usage.md) ## 使用说明 ### 示例代码 1. 在page页面中引入avro ``` import {OhosAvroC, toFile, fromFile} from '@ohos/avro'; ``` 2. 使用 ```js // int 类型 let psInt : AvroNapi = new AvroNapi(); let intStr: string = "{type: 'int'}"; psInt.parse(intStr) let intBuf : number =123; let bufInt: ArrayBuffer = psInt.toBuffer(intBuf); // 序列化 let u8BufInt = new Uint8Array(bufInt); console.log('testTag toBuffer int =', JSON.stringify(u8BufInt));// result:{"0":246,"1":1} let fromInt: number = psInt.fromBuffer(bufInt); // 反序列化 console.log('testTag fromBuffer int =', fromInt);//result:123 console.log('testTag int getName=', psInt.getName());//name:int console.log('testTag isValid int value:123=', psInt.isValid(intBuf));//数据匹配 // string 类型 let psString: AvroNapi = new AvroNapi(); let stringStr: string = "{type: 'string'}"; psString.parse(stringStr); let stringBuf : string ='sdf234'; let bufString: ArrayBuffer = psString.toBuffer(stringBuf); let u8BufString = new Uint8Array(bufString); //result:{"0":12,"1":115,"2":100,"3":102,"4":50,"5":51,"6":52} console.log('testTag toBuffer string =', JSON.stringify(u8BufString)); let fromString: object = psString.fromBuffer(bufString); //result:"sdf234" console.log('testTag fromBuffer string:'+JSON.stringify(fromString)); //name:string console.log('testTag string getName=', psString.getName()); //数据匹配 console.log('testTag isValid string=', psString.isValid(stringBuf)); // fixed类型 let psFixed : AvroNapi = new AvroNapi(); let fixedStr: string = "{type: 'fixed', name: 'num', aliases: ['stooges1', 'stooges2'], size: 2, namespace: 'a'}"; psFixed.parse(fixedStr) let fixedBuf =[0x67, 0xAB]; let buffixed: ArrayBuffer = psFixed.toBuffer(fixedBuf); let u8BufFixed = new Uint8Array(buffixed); //result:{"0":103,"1":171} console.log('testTag toBuffer fixed =', JSON.stringify(u8BufFixed)); const fromFix:object = psFixed.fromBuffer(buffixed); //result:[103,171](16进制为[0x67, 0xAB]) console.log('testTag fromBuffer fixed =', JSON.stringify(fromFix)); //name:num console.log('testTag fixed getName=', psFixed.getName()); //数据匹配 console.log('testTag isValid fixed=', psFixed.isValid(fixedBuf)); //当前Fixed的size:2 console.log('testTag getFixedSize=', psFixed.getFixedSize()); let aliasesFixed:Array = psFixed.getAliases(); //result:["stooges1","stooges2"] console.log('testTag getAliases fixed =', JSON.stringify(aliasesFixed)); let schemaFixed:string = psFixed.getSchema(); //result(avro格式的):"{\"type\": \"fixed\", \"name\": \"num\", \"aliases\": [\"stooges1\", \"stooges2\"], \"size\": 2, \"namespace\": \"a\"}" console.log('testTag getSchema fixed =', JSON.stringify(schemaFixed)); // 数组类型 let psArray : AvroNapi = new AvroNapi(); let arrayStr: string = "{type: 'array', items: 'string'}"; psArray.parse(arrayStr) let arrayBuf =['3443rtr', 'sfrf', 'eryryyh']; let bufarray: ArrayBuffer = psArray.toBuffer(arrayBuf); let u8BufArray = new Uint8Array(bufarray); //result:{"0":6,"1":14,"2":51,"3":52,"4":52,"5":51,"6":114,"7":116,"8":114,"9":8,"10":115,"11":102,"12":114,"13":102,"14":14,"15":101,"16":114,"17":121,"18":114,"19":121,"20":121,"21":104,"22":0} console.log('testTag toBuffer array =', JSON.stringify(u8BufArray)); const fromArray:object = psArray.fromBuffer(bufarray); //result:["3443rtr","sfrf","eryryyh"] console.log('testTag fromBuffer array =', JSON.stringify(fromArray)); //name:array console.log('testTag Array getName=', psArray.getName()); //数据匹配 console.log('testTag isValid array=', psArray.isValid(arrayBuf)); //当前数组的类型为:string console.log('testTag getArrayItemType=', psArray.getArrayItemType()); // map 类型 let psMap: AvroNapi = new AvroNapi(); let mapStr: string = "{type: 'map', values: 'long'}"; psMap.parse(mapStr) const data = new Map([["key1",12343], ["key2",3445]]); let bufmap: ArrayBuffer = psMap.toBuffer(data); let u8Bufmap = new Uint8Array(bufmap); //result:{"0":4,"1":8,"2":107,"3":101,"4":121,"5":49,"6":238,"7":192,"8":1,"9":8,"10":107,"11":101,"12":121,"13":50,"14":234,"15":53,"16":0} console.log('testTag toBuffer map =', JSON.stringify(u8Bufmap)); const aa:object = psMap.fromBuffer(bufmap); //result:{"key1":12343,"key2":3445} console.log('testTag fromBuffer map:'+ JSON.stringify(aa)); //name:map console.log('testTag Map getName=', psMap.getName()); //数据匹配 console.log('testTag isValid map=', psMap.isValid(data)); //当前Map的类型为:long console.log('testTag getMapValueType=', psMap.getMapValueType()); // record 类型 let psRecord : AvroNapi = new AvroNapi(); let recordStr: string = "{type: 'record',name: 'Person',aliases: ['Person1'],fields: [{name: 'age', type: 'int'}, {name: 'name', type: 'string'}]}"; psRecord.parse(recordStr); class petrecordType { "age": number = 0 "name": string = '' } let recordBuf : petrecordType ={"age": 25, "name": "Alice"}; let bufrecord: ArrayBuffer = psRecord.toBuffer(recordBuf); let u8BufRecord = new Uint8Array(bufrecord); //result:{"0":50,"1":10,"2":65,"3":108,"4":105,"5":99,"6":101} console.log('testTag toBuffer record ='+JSON.stringify(u8BufRecord)); const recFromBuff:object = psRecord.fromBuffer(bufrecord); //result:{"age":25,"name":"Alice"} console.log('testTag fromBuffer record ='+JSON.stringify(recFromBuff)); //name:Person console.log('testTag Record getName=', psRecord.getName()); //数据匹配 console.log('testTag isValid record=', psRecord.isValid(recordBuf)); let aliasesRec:Array = psRecord.getAliases(); //result:["Person1"] console.log('testTag getAliases record =', JSON.stringify(aliasesRec)); let schemaRec:string = psRecord.getSchema(); //result(avro格式的):"{\"type\": \"record\",\"name\": \"Person\",\"aliases\": [\"Person1\"],\"fields\": [{\"name\": \"age\", \"type\": \"int\"}, {\"name\": \"name\", \"type\": \"string\"}]}" console.log('testTag getSchema record =', JSON.stringify(schemaRec)); // compareBuffers const hexArray = [0x67, 0xAB]; const uArray = new Uint8Array(hexArray); const buffer1 = uArray.buffer; const hexArray2 = [0x67, 0xAB, 0x11]; const uArray2 = new Uint8Array(hexArray2); const buffer2 = uArray2.buffer; console.log("testTag compareBuffers :" + psArray.compareBuffers(buffer1, buffer2));//小于 // tofile //定义回调函数 let fileSchemaStr: string = "{type: 'record',name: 'User',namespace: 'comexample',fields: [ {name: 'id', type: 'int'}, {name: 'name', type: 'string'}, {name: 'age', type: ['int', 'null']},{name: 'hobbies',type:{type:'array',items: 'string'}}]}"; const path2 = getContext(this).getApplicationContext().filesDir+"/10.avro"; class petrecordType6 { "id": number = 0 "name": string = '' "age": number | null "hobbies": Array } let recordBuf7 = new petrecordType6(); recordBuf7.id = 1; recordBuf7.name = "san"; recordBuf7.age = 25; recordBuf7.hobbies = ["yd", "pb"]; let recordBuf8 = new petrecordType6(); recordBuf8.id = 2; recordBuf8.name = "si"; recordBuf8.age = null; recordBuf8.hobbies = ["yy", "lx"]; let recordBuf9 = new petrecordType6(); recordBuf9.id = 3; recordBuf9.name = "wu"; recordBuf9.age = 30; recordBuf9.hobbies = ["bc", "yy"]; let fileArrayBuf1 =[recordBuf7, recordBuf8, recordBuf9]; //压缩方式支持"deflate"(zlib) "snappy" "lzma" "null"无压缩 try { toFile(path, schema, fileArrayBuf1, "null", (error, data) => { if (error != undefined) { console.log('testTag 序列化失败, error:', error); this.showAlert('序列化失败', '错误信息:' + error); } if (data === undefined) { console.log('testTag 数据有问题!'); this.showAlert('序列化失败', '数据有问题!'); } else { console.error('ps has been created tofile:' + data); this.showAlert('序列化成功', '数据:' + data); } }); } catch (error) { console.log('序列化失败:', error); } // fromfile let fileSchemaStr: string = "{type: 'record',name: 'User',namespace: 'comexample',fields: [ {name: 'id', type: 'int'}, {name: 'name', type: 'string'}, {name: 'age', type: ['int', 'null']},{name: 'hobbies',type:{type:'array',items: 'string'}}]}"; const path2 = getContext(this).getApplicationContext().filesDir+"/10.avro"; try { fromFile(path2, fileSchemaStr, (error, buffer) => { if (error != undefined) { console.log('testTag 反序列化失败:', error); this.showAlert('反序列化失败', '错误信息:' + error); } if (buffer === undefined) { console.log('testTag 反序列化失败,数据有你为他!'); this.showAlert('反序列化失败', '数据有问题!'); } else { //[{"id":1,"name":"san","age":25,"hobbies":["yd","pb"]},{"id":2,"name":"si","age":null,"hobbies":["yy","lx"]},{"id":3,"name":"wu","age":30,"hobbies":["bc","yy"]}] console.error('testTag 反序列化结果:', JSON.stringify(buffer)); this.showAlert('序列化成功', '反序列化结果:' + JSON.stringify(buffer)); } }); } catch (error) { console.log('反序列化失败:', error); } ``` ## 接口说明 | 方法名 | 参数 | 接口描述 | | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | | parse(schema:string) | schema:Avro模式定义 | 解析schema并返回对应的实例 | | toBuffer(val:any) | val: 符合模式的数据对象 | 将数据对象编码序列化为Avro二进制格式的ArrayBuffer | | fromBuffer(buf:ArrayBuffer) | buffer: Avro 编码的二进制数据 | 从Avro二进制格式的ArrayBuffer反序列化为对应类型的数据 | | isValid(val:any) | val:待验证的数据 | 检查给定值是否是有效值。 | | compareBuffers(buf1:ArrayBuffer, buf2:ArrayBuffer) | buf1:待比较的缓冲区
buf2:待比较的缓冲区 | 比较两个二进制缓冲区的大小。返回值说明(按字段定义顺序逐字段比较):
● 负数:val1 < val2
● 0:val1 == val2
● 正数:val1 > val2 | | getName() | - | 获取类型的名称。 | | getArrayItemType() | - | 获取数组的类型。 | | getFixedSize() | - | 获取Fixed类型的大小。 | | getMapValueType() | - | 获取Map的类型。 | | getSchema() | - | 获取Schema字符串,返回的是avro格式的字符串(属性和字符字段都加双引号) | | getAliases() | - | 获取别名(只有Enum、Fixed、Record有name属性,才有别名),结果为字符串数组 | | toFile(path: string, schema: string, val: any, codec: string, callback:AsyncWriteFileCallback) | path:文件路径
schema:Avro模式定义
val:要序列化的数据(record类型支持多条数据传输,record类型请按照数组的形式传递)
codec:压缩方式
callback:异步写文件完成的回调,参数err: string, data: string | 将record数据对象使用指定的schema模式序列化到文件(压缩方式支持"deflate"(zlib) "snappy" "lzma" "null"无压缩)。 | | fromFile(filePath:string,scheam:string,callback:callback) | filePath:文件路径
schema:Avro模式定义
callback:异步读取文件完成的回调,参数err: string, data: ArrayBuffer | 读取已经序列化后的文件使用指定的schema模式转为record类型数据(ArrayBuffer) | ## 关于混淆 - 代码混淆,请查看[代码混淆简介](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/arkts-utils/source-obfuscation.md) - 如果希望avro-js库在代码混淆过程中不会被混淆,需要在混淆规则配置文件obfuscation-rules.txt中添加相应的排除规则: ``` --- ``` ## 约束与限制 在下述版本验证通过: - DevEco Studio 版本:DevEco Studio 5.0.5 Release, OpenHarmony SDK:5.0.5(17) ## 目录结构 ```` |---- ohos_avro | |---- entry # 示例代码文件夹 | |---- avro # avro 库文件夹 | |---- cpp # native模块 | |----- napi # napi实现代码目录 | |----- third_party # 实现引用的三方库jansson、avro、snappy、zlib、lzma | |----- utils # 工具、公共代码和日志接口目录 | |----- type # 对外接口函数目录 | |---- README_zh.MD # 安装使用方法 ```` ## 贡献代码 使用过程中发现任何问题都可以提 [Issue](https://gitcode.com/openharmony-sig/avro/issues) 给组件,当然,也非常欢迎给发 [PR](https://gitcode.com/openharmony-sig/avro/pulls) 。 ## 开源协议 本项目基于 [Apache License 2.0](https://gitcode.com/openharmony-sig/avro/blob/master/LICENSE) ,请自由地享受和参与开源。