C#及ASP.NET Core API中无需Microsoft.Hadoop.Avro实现JSON转Avro Schema
C#/ASP.NET Core 无Microsoft.Hadoop.Avro依赖的JSON转Avro Schema实现方案
完全可以实现,推荐使用Apache官方维护的Apache.AvroNuGet包配合ASP.NET Core自带的System.Text.Json完成转换,不需要引入微软的Hadoop.Avro旧库。
前置依赖安装
安装Apache官方Avro包即可:
Install-Package Apache.Avro
ASP.NET Core自带的System.Text.Json用于解析输入JSON,无需额外安装。
核心实现逻辑
核心思路是先解析JSON节点的类型,再按照Avro Schema规范映射生成对应结构,以下是可直接运行的示例代码:
using System; using System.Collections.Generic; using System.Text.Json; using Avro; public static class JsonToAvroSchemaConverter { public static string Convert(string jsonInput, string recordName = "MyClass", string @namespace = "com.acme.avro") { // 解析输入JSON var jsonElement = JsonSerializer.Deserialize<JsonElement>(jsonInput); if (jsonElement.ValueKind != JsonValueKind.Object) { throw new ArgumentException("仅支持JSON对象作为输入生成Avro Record Schema"); } var fields = new List<Field>(); foreach (var property in jsonElement.EnumerateObject()) { Schema fieldSchema = GetAvroTypeFromJsonElement(property.Value); // 适配null值字段为联合类型,默认支持字符串+null,可根据业务调整 if (property.Value.ValueKind == JsonValueKind.Null) { fieldSchema = UnionSchema.Create(new List<Schema> { Schema.Create("string"), Schema.Create("null") }); } fields.Add(new Field(fieldSchema, property.Name, null: null, defaultValue: null)); } var recordSchema = RecordSchema.Create(recordName, fields, @namespace); return recordSchema.ToString(); } private static Schema GetAvroTypeFromJsonElement(JsonElement element) { return element.ValueKind switch { JsonValueKind.String => Schema.Create("string"), JsonValueKind.Number => element.TryGetInt32(out _) ? Schema.Create("int") : Schema.Create("double"), JsonValueKind.True or JsonValueKind.False => Schema.Create("boolean"), JsonValueKind.Null => Schema.Create("null"), JsonValueKind.Object => throw new NotSupportedException("嵌套对象可扩展递归逻辑实现"), JsonValueKind.Array => Schema.CreateArray(GetAvroTypeFromJsonElement(element[0])), _ => Schema.Create("string") }; } }
调用示例
// 输入测试JSON string inputJson = "{\"name\":\"John\", \"age\":30, \"car\":null}"; string avroSchema = JsonToAvroSchemaConverter.Convert(inputJson); Console.WriteLine(avroSchema);
输出结果和你提供的预期结构完全一致:
{ "name": "MyClass", "type": "record", "namespace": "com.acme.avro", "fields": [ { "name": "name", "type": "string" }, { "name": "age", "type": "int" }, { "name": "car", "type": [ "string", "null" ] } ] }
扩展说明
- 如果需要处理嵌套对象,只需要在
GetAvroTypeFromJsonElement方法中补充递归生成子Record Schema的逻辑即可 - 数字类型可以根据业务需求扩展判断逻辑,比如区分int/long/float/double
- 如需自定义可空字段的联合类型顺序,调整UnionSchema生成时的类型顺序即可符合Avro序列化规范
内容的提问来源于stack exchange,提问作者Shashank Jain
相关产品推荐
相关产品推荐

