You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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:

  1. 实现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);
    }
}
  1. 给枚举类型添加TypeConverter特性:
[TypeConverter(typeof(EnumDescriptionTypeConverter))]
public enum SampleEnum
{
    [Description("Sample")]
    SampleAbc
}
  1. 直接使用默认Bind方法:
var sampleConfig = new SampleConfig();
configuration.GetSection("section").Bind(sampleConfig);

内容的提问来源于stack exchange,提问作者vivek86

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 19:20:34