.NET 6独立进程Azure Functions中使用Newtonsoft.Json的方案咨询
Azure Functions中使用Newtonsoft.Json绑定Azure App Configuration配置(兼容System.Text.Json方案)
方案一:沿用Newtonsoft.Json转换器实现配置绑定
Azure Functions非Mvc场景下无法通过AddMvc().AddNewtonsoftJson全局配置序列化逻辑,我们可以绕开默认的Bind方法,直接将配置节序列化为JSON字符串,再用Newtonsoft.Json反序列化,从而复用已有的转换器。
步骤1:实现配置节转JSON的扩展方法(兼容旧.NET版本)
如果项目使用的.NET版本不支持IConfigurationSection.GetRawJson(),可以实现以下扩展方法:
using Newtonsoft.Json.Linq; using Microsoft.Extensions.Configuration; public static class ConfigurationJsonExtensions { public static string ToJson(this IConfigurationSection section) { var jObject = new JObject(); foreach (var child in section.GetChildren()) { if (child.GetChildren().Any()) { jObject[child.Key] = JToken.Parse(child.ToJson()); } else { jObject[child.Key] = JToken.FromObject(child.Value); } } return jObject.ToString(); } }
步骤2:使用现有Newtonsoft.Json枚举转换器
假设你已实现处理Description属性的枚举转换器:
using Newtonsoft.Json; using System.ComponentModel; using System.Reflection; public class EnumDescriptionConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType.IsEnum; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var value = reader.Value.ToString(); var enumType = Nullable.GetUnderlyingType(objectType) ?? objectType; foreach (var field in enumType.GetFields()) { if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attr && attr.Description == value) { return Enum.Parse(enumType, field.Name); } } // 找不到匹配的Description时,回退到默认枚举解析 return Enum.Parse(enumType, value); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var field = value.GetType().GetField(value.ToString()); var attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; writer.WriteValue(attr?.Description ?? value.ToString()); } }
步骤3:绑定配置
// 初始化Newtonsoft序列化配置,添加你的自定义转换器 var serializerSettings = new JsonSerializerSettings(); serializerSettings.Converters.Add(new EnumDescriptionConverter()); // 将配置节转为JSON并反序列化到目标类型 var sectionJson = configuration.GetSection("section").ToJson(); var sampleConfig = JsonConvert.DeserializeObject<SampleConfig>(sectionJson, serializerSettings);
如果是.NET 6+,可直接用configuration.GetSection("section").GetRawJson()替代ToJson()方法简化代码。
方案二:使用System.Text.Json实现相同枚举转换需求
如果不想依赖Newtonsoft.Json,可以通过以下两种方式实现:
方式1:System.Text.Json反序列化配置节
首先实现处理Description属性的System.Text.Json枚举转换器:
using System.Text.Json; using System.Text.Json.Serialization; using System.ComponentModel; using System.Reflection; public class EnumDescriptionJsonConverter : JsonConverterFactory { public override bool CanConvert(Type typeToConvert) { return typeToConvert.IsEnum || (Nullable.GetUnderlyingType(typeToConvert)?.IsEnum ?? false); } public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { var enumType = Nullable.GetUnderlyingType(typeToConvert) ?? typeToConvert; var converterType = typeof(EnumDescriptionConverter<>).MakeGenericType(enumType); return (JsonConverter)Activator.CreateInstance(converterType); } private class EnumDescriptionConverter<TEnum> : JsonConverter<TEnum> where TEnum : struct, Enum { public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var value = reader.GetString(); foreach (var field in typeof(TEnum).GetFields()) { if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attr && attr.Description == value) { return (TEnum)Enum.Parse(typeof(TEnum), field.Name); } } if (Enum.TryParse(value, out TEnum result)) { return result; } throw new JsonException($"无法将值 '{value}' 转换为枚举类型 {typeof(TEnum).Name}"); } public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) { var field = typeof(TEnum).GetField(value.ToString()); var attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute; writer.WriteStringValue(attr?.Description ?? value.ToString()); } } }
然后绑定配置:
var jsonOptions = new JsonSerializerOptions(); jsonOptions.Converters.Add(new EnumDescriptionJsonConverter()); var sectionJson = configuration.GetSection("section").ToJson(); // .NET 6+可用GetRawJson() var sampleConfig = JsonSerializer.Deserialize<SampleConfig>(sectionJson, jsonOptions);
方式2:自定义TypeConverter实现默认配置绑定
如果希望继续使用configuration.GetSection("section").Bind(sampleConfig)的方式,可以给枚举类型添加自定义TypeConverter:
- 实现TypeConverter:
using System.ComponentModel; using System.Reflection; public class EnumDescriptionTypeConverter : TypeConverter { public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType); } public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) { if (value is string strValue) { var enumType = context.PropertyDescriptor.PropertyType; enumType = Nullable.GetUnderlyingType(enumType) ?? enumType; foreach (var field in enumType.GetFields()) { if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attr && attr.Description == strValue) { return Enum.Parse(enumType, field.Name); } } return Enum.Parse(enumType, strValue); } return base.ConvertFrom(context, culture, value); } }
- 给枚举类型添加TypeConverter特性:
[TypeConverter(typeof(EnumDescriptionTypeConverter))] public enum SampleEnum { [Description("Sample")] SampleAbc }
- 直接使用默认Bind方法:
var sampleConfig = new SampleConfig(); configuration.GetSection("section").Bind(sampleConfig);
内容的提问来源于stack exchange,提问作者vivek86
相关产品推荐
相关产品推荐

