如何实现Dart对象实例与字节互转以通过TCP传输?
在Dart中实现对象的二进制序列化(类似Java Serializable)
Dart没有内置的Serializable接口,但可以通过以下几种方式实现对象与字节的互转,满足你TCP Socket传输的需求:
方案1:手动实现序列化/反序列化(无依赖)
适合结构简单的类,完全自定义字节格式,无需额外库。
示例代码
首先定义MessageDto类,添加序列化和反序列化方法:
import 'dart:convert'; import 'dart:typed_data'; class MessageDto { final String msg; final String action; final String method; MessageDto({required this.msg, required this.action, required this.method}); // 将对象转为字节列表 Uint8List toBytes() { final msgBytes = utf8.encode(msg); final actionBytes = utf8.encode(action); final methodBytes = utf8.encode(method); // 用4字节存储每个字符串的长度(大端序),再拼接字符串字节 final buffer = BytesBuilder(); buffer.add(_int32ToBytes(msgBytes.length)); buffer.add(msgBytes); buffer.add(_int32ToBytes(actionBytes.length)); buffer.add(actionBytes); buffer.add(_int32ToBytes(methodBytes.length)); buffer.add(methodBytes); return buffer.toBytes(); } // 从字节列表重建对象 factory MessageDto.fromBytes(Uint8List bytes) { final reader = ByteData.view(bytes.buffer); int offset = 0; // 读取msg字段 final msgLength = reader.getInt32(offset, Endian.big); offset += 4; final msg = utf8.decode(bytes.sublist(offset, offset + msgLength)); offset += msgLength; // 读取action字段 final actionLength = reader.getInt32(offset, Endian.big); offset += 4; final action = utf8.decode(bytes.sublist(offset, offset + actionLength)); offset += actionLength; // 读取method字段 final methodLength = reader.getInt32(offset, Endian.big); offset += 4; final method = utf8.decode(bytes.sublist(offset, offset + methodLength)); return MessageDto(msg: msg, action: action, method: method); } // 辅助方法:将int32转为大端序字节 Uint8List _int32ToBytes(int value) { final byteData = ByteData(4); byteData.setInt32(0, value, Endian.big); return byteData.buffer.asUint8List(); } }
使用方式
void main(List<String> arguments) async { MessageDto messageDto = MessageDto( msg: 'essa é a menssagem', action: 'action', method: 'method', ); // 对象转字节 Uint8List buffer = messageDto.toBytes(); send(buffer); // 替换为你的TCP发送逻辑 // 服务端接收后重建对象 MessageDto received = MessageDto.fromBytes(buffer); print(received.msg); // 输出: essa é a menssagem }
方案2:使用Protobuf(适合跨语言场景)
Protobuf是Google的二进制序列化协议,支持多语言,生成的代码高效且维护方便。
步骤
安装依赖:
dart pub add protobuf dart pub global activate protoc_plugin确保
protoc编译器和protoc_plugin的bin目录在系统PATH中。定义.proto文件(
message.proto):syntax = "proto3"; message MessageDto { string msg = 1; string action = 2; string method = 3; }生成Dart代码:
protoc --dart_out=./lib ./message.proto使用生成的类:
import 'package:protobuf/protobuf.dart'; import 'message.pb.dart'; // 生成的Dart文件 void main() { final messageDto = MessageDto() ..msg = 'essa é a menssagem' ..action = 'action' ..method = 'method'; // 对象转字节 Uint8List buffer = messageDto.writeToBuffer(); send(buffer); // 服务端重建对象 final received = MessageDto.fromBuffer(buffer); print(received.msg); }
方案3:使用built_value(适合复杂对象)
built_value是Dart的序列化库,支持二进制序列化,同时提供不可变对象、哈希等特性。
步骤
添加依赖(
pubspec.yaml):dependencies: built_value: ^8.6.1 built_collection: ^5.1.1 dev_dependencies: build_runner: ^2.4.4 built_value_generator: ^8.6.1定义MessageDto类(
message_dto.dart):import 'package:built_value/built_value.dart'; import 'package:built_value/serializer.dart'; import 'package:built_value/builder.dart'; part 'message_dto.g.dart'; abstract class MessageDto implements Built<MessageDto, MessageDtoBuilder> { String get msg; String get action; String get method; MessageDto._(); factory MessageDto([void Function(MessageDtoBuilder) updates]) = _$MessageDto; // 对象转字节 Uint8List toBytes() { return serializers.serializeWith(MessageDto.serializer, this) as Uint8List; } // 字节转对象 static MessageDto fromBytes(Uint8List bytes) { return serializers.deserializeWith(MessageDto.serializer, bytes)!; } static Serializer<MessageDto> get serializer => _$messageDtoSerializer; } // 配置序列化器 Serializers serializers = (_$serializers.toBuilder() ..addBuilderFactory( const FullType(MessageDto), () => MessageDtoBuilder(), )) .build();生成代码:
dart run build_runner build使用方式:
void main() { final messageDto = MessageDto((b) => b ..msg = 'essa é a menssagem' ..action = 'action' ..method = 'method'); Uint8List buffer = messageDto.toBytes(); send(buffer); final received = MessageDto.fromBytes(buffer); print(received.msg); }
内容的提问来源于stack exchange,提问作者user2859203
相关产品推荐
相关产品推荐

