.NET 8 Azure Functions隔离进程中Service Bus JObject序列化异常
问题分析与解决思路
核心问题根源
.NET 8 隔离进程模式的 Azure Functions,其绑定系统默认使用 System.Text.Json 进行对象序列化,而非你代码中依赖的 Newtonsoft.Json。你全局配置的 JsonConvert.DefaultSettings 仅对手动调用 Newtonsoft 序列化的场景生效,无法影响 Functions 绑定的自动序列化逻辑,这就导致返回的 Envelope<JObject> 在被 System.Text.Json 处理时,错误解析了 JObject 的内部结构,出现序列化不完整(表现为数组嵌套空结构)的问题。
具体解决方案
方案一:手动序列化返回字符串(快速生效)
直接将函数返回类型改为字符串,手动使用 Newtonsoft.Json 完成序列化,让 Service Bus 输出绑定直接发送已序列化好的字符串内容,绕开自动序列化的冲突:
[Function(nameof(HandleQueueA))] [ServiceBusOutput(OutputQueueB, Connection = "ServiceBusConnection")] public async Task<string> Run( [ServiceBusTrigger(StartQueueA, Connection = "ServiceBusConnection")] ServiceBusReceivedMessage message) { var eventData = JsonConvert.DeserializeObject<Envelope<JToken>>(message.Body); // 业务逻辑处理 return JsonConvert.SerializeObject(eventData); }
方案二:配置 Functions 使用 Newtonsoft.Json 作为默认序列化器
通过扩展包让 Functions 绑定系统切换为 Newtonsoft.Json,复用你已有的全局序列化配置:
- 安装 NuGet 包:
Microsoft.Azure.Functions.Worker.Extensions.NewtonsoftJson - 在
Program.cs中替换默认序列化器并注入你的配置:
var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults(worker => { // 启用 Newtonsoft.Json 作为绑定的默认序列化器 worker.UseNewtonsoftJson(); }) .ConfigureServices(services => { // 配置 Newtonsoft.Json 规则,与你原全局配置对齐 services.Configure<NewtonsoftJsonSerializerOptions>(options => { options.DefaultValueHandling = DefaultValueHandling.Include; options.NullValueHandling = NullValueHandling.Ignore; options.ContractResolver = new CamelCasePropertyNamesContractResolver(); options.Converters.Add(new StringEnumConverter()); options.Converters.Add(new IsoDateTimeConverter()); }); }) .Build(); host.Run();
修改完成后,函数返回 Envelope<JObject> 时,输出绑定会自动使用你的 Newtonsoft 配置完成序列化,无需手动处理。
方案三:统一迁移到 System.Text.Json(长期维护)
如果愿意替换序列化引擎为官方默认的 System.Text.Json,可以做以下调整:
- 反序列化时使用
JsonElement替代JToken/JObject:
var eventData = JsonSerializer.Deserialize<Envelope<JsonElement>>(message.Body.ToString());
- 在
Program.cs中配置System.Text.Json的全局规则,同时为自定义类型DateTimeEpoch编写转换器:
// 自定义 DateTimeEpoch 的 System.Text.Json 转换器 public class DateTimeEpochConverter : JsonConverter<DateTimeEpoch> { public override DateTimeEpoch Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { // 实现反序列化逻辑 } public override void Write(Utf8JsonWriter writer, DateTimeEpoch value, JsonSerializerOptions options) { // 实现序列化逻辑,对齐原 CamelCase 等规则 writer.WriteStartObject(); writer.WriteString("dateTime", value.DateTime.ToString("o")); writer.WriteNumber("epoch", value.Epoch); writer.WriteEndObject(); } } // 全局配置 var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults(worker => { worker.UseSystemTextJson(options => { options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull; options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(new DateTimeEpochConverter()); }); }) .Build(); host.Run();
内容的提问来源于stack exchange,提问作者Hanna Holasava
相关产品推荐
相关产品推荐

