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

动态生成settings.json时嵌套类型转换异常问题求助

泛型配置类动态更新settings.json时嵌套类型转换异常

我需要在类库中实现一个类,能够从泛型对象T动态生成settings.json文件,并且当T的结构变更时自动增删对应的属性。目前代码可以正常创建JSON文件,但修改T后运行时抛出异常:

System.ArgumentException: 'Object of type 'System.Text.Json.JsonElement' cannot be converted to type 'Common.Settings.JWTSecuritySettings'.'

该异常与T中的嵌套配置类有关(例如AppSettings包含的JWTSecuritySettings、DBConnectionSettings)。尝试移除UpdateJsonObject方法中的if判断逻辑后,问题仍未解决,反而出现了其他错误。

核心代码

Settings类实现

using Microsoft.Extensions.Options;
using System.Reflection;
using System.Text.Json;

namespace Common.Settings
{
    public static class Settings
    {
        public static string FilePath { get; private set; }
        public static string FileName { get; private set; }


        public static T UseSettings<T>(this IServiceCollection services, Action<Options>? configureOptions) where T : class, new()
        {
            var options = new Options();
            configureOptions?.Invoke(options);

            FilePath = options.Path;
            FileName = options.FileName;
            var filePath = Path.Combine(options.Path, options.FileName);

            if (!File.Exists(filePath))
            {
                Directory.CreateDirectory(options.Path);
                var settings = CreateDefaultSettings<T>();
                var defaultSettings = JsonSerializer.Serialize(settings);
                File.WriteAllText(filePath, defaultSettings);
            }

            var json = File.ReadAllText(filePath);
            var rootElement = JsonDocument.Parse(json).RootElement;
            var properties = typeof(T).GetProperties();
            var mismatchFound = false;

            foreach (var property in properties)
            {
                if (!rootElement.TryGetProperty(property.Name, out var propertyElement))
                {
                    mismatchFound = true;
                    Console.WriteLine($"Property '{property.Name}' not found in {options.FileName}");
                    rootElement = UpdateJsonObject<T>(rootElement, filePath);
                    continue;
                }
            }

            if (mismatchFound)
            {
                Console.WriteLine($"** Property mismatches found in {options.FileName} JSON configuration. The missing properties were added to {options.FileName}. **");
            }

            var deserializedSettings = JsonSerializer.Deserialize<T>(json);
            services.AddSingleton(deserializedSettings);
            return deserializedSettings;
        }

        private static T CreateDefaultSettings<T>() where T : class, new()
        {
            var settings = new T();
            var properties = typeof(T).GetProperties();

            foreach (var property in properties)
            {
                if (property.PropertyType.IsClass && property.PropertyType != typeof(string))
                {
                    var nestedSettings = typeof(Settings).GetMethod("CreateDefaultSettings", BindingFlags.NonPublic | BindingFlags.Static)
                        .MakeGenericMethod(property.PropertyType)
                        .Invoke(null, null);

                    property.SetValue(settings, nestedSettings);
                }
            }

            return settings;
        }

        private static JsonElement UpdateJsonObject<T>(JsonElement element, string filePath) where T : class, new()
        {
            var settings = new T();
            var properties = typeof(T).GetProperties();

            foreach (var property in properties)
            {
                Console.WriteLine(property);
                if (property.PropertyType.IsClass && property.PropertyType != typeof(string))
                {
                    var nestedSettings = typeof(Settings).GetMethod("UpdateJsonObject", BindingFlags.NonPublic | BindingFlags.Static)
                        .MakeGenericMethod(property.PropertyType)
                        .Invoke(null, [element, filePath]);

                    if (element.TryGetProperty(property.Name, out var ele))
                    {
                        property.SetValue(settings, ele);
                    }
                    else
                    {
                        property.SetValue(settings, nestedSettings);
                    }

                }
            }
            var defaultSettings = JsonSerializer.Serialize(settings);
            File.WriteAllText(filePath, defaultSettings);
            return JsonDocument.Parse(defaultSettings).RootElement;
        }

    }


    public class Options
    {
        public string Path { get; set; } = "config";
        public string FileName { get; set; } = "settings.json";

    }
}

嵌套配置类定义

public class AppSettings{
    public string Servicename { get; set; }
    public string AppDomain { get; set; }
    public JWTSecuritySettings JWTSettings { get; set; }
    public DBConnectionSettings DBSettings { get; set; }
    public string TenantDBEncryptionKey { get; set; }
  }

  public class JWTSecuritySettings
  {
    public string PrivateKey { get; set; }
    public string PublicKey { get; set; }
    public string Issuer { get; set; } = "http://localhost:5001";
  }

  public class DBConnectionSettings
  {
    public string ConnectionString { get; set; } ="Host=localhost;Database=DEVDB;Username=postgres;Password=post";
    public string DBName { get; set; }
  }

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 12:17:01