其他
在 .NET 中做 API、消息或持久化序列化选型与…
适用于 .NET 应用选择序列化格式、从 Newtonsoft.Json 迁移、实现 AOT 兼容序列化、设计跨进程 wire format 或优化序列化性能。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 48/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 85/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 55/100 ×0.15
适用场景
在 .NET 中做 API、消息或持久化通用
解决思路
- 按场景执行格式选型:API、配置、Web 客户端使用 System.Text.Json(source gen);服务间/gRPC wire format 使用 Protobuf;高吞吐缓存、实时消息使用 MessagePack;新 AOT 项目不要用 Newtonsoft.Json。
- 优先使用基于 schema 的序列化(Protobuf、MessagePack、System.Text.Json source gen)处理任何跨进程边界的数据;避免反射式序列化(Newtonsoft.Json、BinaryFormatter)。
- 避免使用 BinaryFormatter(安全漏洞且已弃用)、Newtonsoft.Json 默认方式(payload 含类型名)、DataContractSerializer(复杂、版本控制差)和 XML(冗长、慢、复杂)。
- System.Text.Json 使用 source generators:创建 partial class 继承 JsonSerializerContext,并用 [JsonSerializable(typeof(...))] 标注所有需要序列化的类型,包括集合类型如 List<Order>。
- 使用生成的上下文序列化/反序列化:JsonSerializer.Serialize(order, AppJsonContext.Default.Order) 和 JsonSerializer.Deserialize(json, AppJsonContext.Default.Order)。
- 通过 JsonSerializerOptions 配置序列化,例如 PropertyNamingPolicy = JsonNamingPolicy.CamelCase、TypeInfoResolver = AppJsonContext.Default。
- ASP.NET Core 集成:Minimal APIs 使用 builder.Services.ConfigureHttpJsonOptions(options => options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonContext.Default)); MVC 使用 builder.Services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonContext.Default));
- 组合多个 JsonSerializerContext:使用 JsonTypeInfoResolver.Combine(AppJsonContext.Default, CatalogJsonContext.Default, InventoryJsonContext.Default) 设置 TypeInfoResolver。
- 在 JsonSerializerContext 上使用 [JsonSourceGenerationOptions(...)] 配置 PropertyNamingPolicy、DefaultIgnoreCondition、WriteIndented 等。
- 处理多态:在基类/抽象类上用 [JsonDerivedType(typeof(...), "discriminator")] 标注派生类型,并把基类类型加入 [JsonSerializable]。
- Protobuf:添加 PackageReference Google.Protobuf 和 Grpc.Tools(PrivateAssets="All")。定义 .proto 文件,使用 proto3 syntax、字段编号、repeated、google.protobuf.Timestamp 等。
- 独立使用 Protobuf(不依赖 gRPC):用 order.ToByteArray() 序列化,OrderMessage.Parser.ParseFrom(bytes) 反序列化,order.WriteTo(stream) 写入流。
- 在 .csproj 中注册 proto 文件:<Protobuf Include="Protos\*.proto" GrpcServices="Both" />;不要省略 GrpcServices 属性,否则会同时生成 client 和 server stub。
- Protobuf 版本控制规则:新字段使用新字段编号;删除字段时保留编号并写 reserved;不要修改字段类型;不要复用字段编号。
- MessagePack:添加 PackageReference MessagePack 和 MessagePack.SourceGenerator。
- MessagePack 类型标注:用 [MessagePackObject] 标注 partial class,用 [Key(0)]、[Key(1)] 等整数 key 标注属性。
- MessagePack 序列化:MessagePackSerializer.Serialize(order) 和 MessagePackSerializer.Deserialize<Order>(bytes)。
- MessagePack 压缩:使用 MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4BlockArray) 处理大 payload。
- MessagePack AOT 解析器:设置 MessagePackSerializer.DefaultOptions = MessagePackSerializerOptions.Standard.WithResolver(GeneratedResolver.Instance)。
- Wire 兼容:旧代码必须容忍未知字段;Protobuf/MessagePack 自动跳过未知字段;System.Text.Json 配置 UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip。
- 先读后写部署:先部署能反序列化新格式的代码(deserializer),再启用新格式序列化(serializer);用 manifest/version 字段如 "Order.V1"、"Order.V2" 路由反序列化。
- 不要嵌入类型名:payload 中使用显式 discriminator 如 { "type": "order", "id": 123 },不要使用 { "$type": "MyApp.Order, MyApp" }。
- 性能优化:复用 JsonSerializerOptions;使用 JsonSerializerContext 消除 warm-up;流式场景使用 Utf8JsonWriter/Utf8JsonReader;Protobuf 二进制数据用 ByteString 而不是 base64 字符串;大 payload 启用 MessagePack LZ4 压缩。
- 避免反射式序列化用于 Native AOT/trimming:不要用 JsonConvert.SerializeObject/DeserializeObject;不要用未提供 context 的 JsonSerializer.Serialize(order);应使用 source-generated context。
- 从 Newtonsoft.Json 迁移:1) 将 JsonConvert.SerializeObject/DeserializeObject 替换为 JsonSerializer.Serialize/Deserialize;2) [JsonProperty] 替换为 [JsonPropertyName];3) JsonConverter 基类替换为 System.Text.Json 的 JsonConverter<T>;4) 为所有序列化类型创建 JsonSerializerContext 并加 [JsonSerializable];5) 将 JObject/JToken 动态访问替换为 JsonDocument/JsonElement 或强类型模型;6) 测试序列化 round-trips,因为 attribute 语义不同。
- Akka.NET 序列化:在 HOCON 配置中注册 serializers 和 serialization-bindings,例如 messagepack = "Akka.Serialization.MessagePackSerializer, Akka.Serialization.MessagePack",并将消息接口绑定到 messagepack。
- 遵循关键原则:JSON 默认用 System.Text.Json + source generators;服务间二进制用 Protobuf;高吞吐缓存/实时用 MessagePack;新 AOT 项目永不用 Newtonsoft.Json;ASP.NET Core 中始终注册 JsonSerializerContext;所有序列化类型都必须标注,source generators 只为列出的类型生成代码。
- 避免常见错误:AOT 项目不要无 context 调用 JsonSerializer.Serialize(obj);不要忘记在 [JsonSerializable] 中列出集合类型;不要将 Newtonsoft.Json 的 [JsonProperty] 与 System.Text.Json 混用(会被静默忽略);不要在同一类型层次中混用 MessagePack 整数 [Key] 和字符串 [Key];不要省略 <Protobuf> 项的 GrpcServices 属性。
适用边界 · 注意事项
- 不要用于非 .NET 项目或不涉及 .NET 序列化的场景。
- 不要在 Native AOT 或 trimming 场景中使用反射式序列化(如 Newtonsoft.Json、无 source gen 的 System.Text.Json)。
- 不要在新项目或跨进程边界使用 BinaryFormatter、DataContractSerializer、XML 或嵌入类型名的 JSON。