从appsettings阅读JSON对象,json

pw136qt2  于 2023-05-02  发布在  其他
关注(0)|答案(7)|浏览(129)

**TL;DR:**如何从appsettings中读取复杂的JSON对象。json?

我有一个.NET Core 2。x应用程序具有多种类型的配置值。appsettings.json看起来像下面的代码片段,我试图将ElasticSearch:MyIndex:mappings的值作为单个字符串或JSON对象读取。

{
"ConnectionStrings": {
    "redis": "localhost"
},
"Logging": {
    "IncludeScopes": false,
    "Debug": {
        "LogLevel": {
            "Default": "Warning"
        }
    },
    "Console": {
        "LogLevel": {
            "Default": "Warning"
        }
    }
},
"ElasticSearch": {
    "hosts": [ "http://localhost:9200" ],
    "MyIndex": {
        "index": "index2",
        "type": "mytype",
        "mappings": {
            "properties": {
                "property1": {
                    "type": "string",
                    "index": "not_analyzed"
                },
                "location": {
                    "type": "geo_point"
                },
                "code": {
                    "type": "string",
                    "index": "not_analyzed"
                }
            }
        }
    }
}
}

通过调用Configuration.GetValue<string>("ElasticSearch:MyIndex:index"),我能够毫无问题地读取简单的配置值(键:值对)。

配置。GetSectionConfiguration.GetSection("ElasticSearch:MyIndex:mappings").ValueValue提供了一个null值。
配置。GetValueConfiguration.GetValue<string>("ElasticSearch:MyIndex:mappings")也返回空值。这对我来说是有意义的,因为基于上述尝试,该部分具有空值。
配置。GetValueConfiguration.GetValue<JToken>("ElasticSearch:MyIndex:mappings")也返回空值。这对我来说也是有意义的,原因和上面一样。

zqry0prt

zqry0prt1#

Dictionary<string,object> settings = Configuration
    .GetSection("ElasticSearch")
    .Get<Dictionary<string,object>>();
string json = JsonConvert.SerializeObject(settings);
wbrvyc0a

wbrvyc0a2#

最终的解决方案比我最初尝试的任何方法都要简单得多:阅读应用程序设置。json和其他JSON格式的文件一样。

JToken jAppSettings = JToken.Parse(
  File.ReadAllText(Path.Combine(Environment.CurrentDirectory, "appsettings.json"))
);

string mapping = jAppSettings["ElasticSearch"]["MyIndex"]["mappings"];
xzv2uavs

xzv2uavs3#

将JSON对象转换为转义字符串。要做到这一点,你很可能只需要转义所有的双引号,并把它放在 * 一行 *,所以它看起来像这样:

"ElasticSearch": "{\"hosts\": [ \"http://localhost:9200\" ],\"MyIndex\": {\"index\"... "

然后你可以将它读入一个字符串,可以通过使用以下命令进行解析:

Configuration["ElasticSearch"]

这个解决方案并不适合每个人,因为查看或更新转义的json并不有趣,但是如果你只打算很少更改这个配置设置,那么它可能不是最坏的主意。

beq87vna

beq87vna4#

@chris31389的解决方案很好,收到了我的投票。然而,我的情况需要一个更通用的解决方案。

private static IConfiguration configuration;

public static TConfig ConfigurationJson<TConfig>(this string key)
{
  var keyValue = GetJson();
  return Newtonsoft.Json.JsonConvert.DeserializeObject<TConfig>(keyValue);
  
  string GetJson()
  {
     if (typeof(TConfig).IsArray)
     {
         var dictArray = configuration
             .GetSection(key)
             .Get<Dictionary<string, object>[]>();
                
         return Newtonsoft.Json.JsonConvert.SerializeObject(dictArray);
     }

      var dict = configuration
          .GetSection(key)
          .Get<Dictionary<string, object>[]>();
      return Newtonsoft.Json.JsonConvert.SerializeObject(dict);
   }
}

备注:

  • Nuget Microsoft.Extensions.Configuration.活页夹为必填项
  • 正如上面所指出的@chris31389,你必须反序列化到一个字典,然后重新序列化到一个字符串,否则你会得到空值。这将不起作用
configuration
  .GetSection(key)
  .Get<TConfig>()
  • 如果您尝试反序列化数组,则需要Dictionary[]。这就是为什么其他解决方案有时不起作用的原因。
wz8daaqr

wz8daaqr5#

读取配置:

IConfiguration configuration = new ConfigurationBuilder()
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true).Build();

然后您可以创建一个POCO来MapJSON文件的结构(或其一部分)。例如,如果类名为ConnectionStringsConfiguration

public class ConnectionStringsConfiguration { public string Redis {get; set;} }

然后用途:

ConnectionStringsConfiguration appConfig = configuration.GetSection("ConnectionStrings").Get<ConnectionStringsConfiguration>();
vbopmzt1

vbopmzt16#

我通过将配置数据绑定到一个类来获取配置数据,并在任何地方作为服务使用,在configureservices中我添加了这个类

services.Configure<SiteSettings>(options => Configuration.Bind(options));

然后在控制器中,我可以通过依赖注入来访问它,如下所示:

private readonly IOptionsSnapshot<SiteSettings> _siteSetting;
public TestController(IOptionsSnapshot<SiteSettings> siteSetting) ......
pod7payv

pod7payv7#

简单示例

使用扩展方法:

public static class ConfigurationExtensions
{
    public static T GetOptions<T>(this IConfiguration configuration)
        where T : class, new()
        => configuration.GetSection(typeof(T).Name).Get<T>() ?? new T();
}

那就这样叫吧:

var loggingOptions = configuration.GetOptions<LoggingOptions>();

不那么简单的例子

下面是一个使用嵌套POCO和数组的更高级的示例。以下是配置POCO:

public class DynamicDnsUpdaterOptions
{
    public Int32 ClientTimeoutInMinutes { get; set; } = 1;
    public Int32 UpdateIntervalInMinutes { get; set; } = 5;
    public Int32 MonitorStatusInMinutes { get; set; } = 60;
    public Int32 ForceUpdateInDays { get; set; } = 30;
    public Boolean EnablePasswordEncryption { get; set; }
    public IReadOnlyCollection<Domain> Domains { get; set; } = Array.Empty<Domain>();
    public IReadOnlyCollection<Provider> Providers { get; set; } = Array.Empty<Provider>();
    public IReadOnlyCollection<IpChecker> IpCheckers { get; set; } = Array.Empty<IpChecker>();
}

public class Domain
{
    public string DomainName { get; set; } = String.Empty;
    public DnsProviderType ProviderType { get; set; }
    public string HostedZoneId { get; set; } = String.Empty;
    public string AccessID { get; set; } = String.Empty;
    public string SecretKey { get; set; } = String.Empty;
    public Int32 MinimalUpdateIntervalInMinutes { get; set; }
    public string LastIpAddress { get; set; } = String.Empty;
    public DateTime? LastUpdatedDateTime { get; set; }
    public string ChangeStatusID { get; set; } = String.Empty;
    public ICollection<String> HistoricalIPAddress { get; set; } = new List<String>();
    public UpdateReasonType LastUpdatedReason { get; set; }
}

public class Provider
{
    public DnsProviderType ProviderType { get; set; }
    public String ProviderUrl { get; set; } = String.Empty;
    public String ApiKey { get; set; } = String.Empty;
}

public class IpChecker
{
    public IpCheckerType IpCheckerType { get; set; }
    public ClientType ClientType { get; set; }
    public string IpCheckerUrl { get; set; } = String.Empty;
}

public enum DnsProviderType
{
    AMAZON_ROUTE_53
}

public enum IpCheckerType
{
    DYN_DNS,
    JSON_IP,
    CUSTOM
}

public enum UpdateReasonType
{
    FORCED,
    CHANGED
}

public enum ClientType
{
    WEB_HTTP
}

相应的配置部分如下所示:

{
    "DynamicDnsUpdaterOptions": {
        "ClientTimeoutInMinutes": 1,
        "UpdateIntervalInMinutes": 6,
        "MonitorStatusInMinutes": 1,
        "ForceUpdateInDays": 30,
        "EnablePasswordEncryption": false,
        "Domains": [
            {
                "DomainName": "something.example.com",
                "ProviderType": "AMAZON_ROUTE_53",
                "HostedZoneId": "<HostedZoneId>",
                "AccessID": "<AccessID>",
                "SecretKey": "<SecretKey>",
                "MinimalUpdateIntervalInMinutes": "5",
                "LastIpAddress": "192.168.111.222",
                "LastUpdatedDateTime": "2015-02-21T19:29:12.8381639Z",
                "ChangeStatusID": "",
                "HistoricalIPAddress": [],
                "LastUpdatedReason": "CHANGED"
            }
        ],
        "Providers": [
            {
                "ProviderType": "AMAZON_ROUTE_53",
                "ProviderUrl": "https://route53.amazonaws.com"
            }
        ],
        "IpCheckers": [
            {
                "IpCheckerType": "JSON_IP",
                "ClientType": "WEB_HTTP",
                "IpCheckerUrl": "http://www.jsonip.com/"
            },
            {
                "IpCheckerType": "DYN_DNS",
                "ClientType": "WEB_HTTP",
                "IpCheckerUrl": "http://checkip.dyndns.com/"
            },
            {
                "IpCheckerType": "CUSTOM",
                "ClientType": "WEB_HTTP",
                "IpCheckerUrl": "http://ipv4.icanhazip.com/"
            }
        ]
    }
}

然后像这样取它:

var options = configuration.GetOptions<DynamicDnsUpdaterOptions>();

注意事项

*请确保您的POCO包含合理的默认值。如果appsettings.json中不存在该节,或者无法成功绑定到POCO,则将使用POCO的默认值。

  • POCO必须使用属性,而不是字段。
  • 列表或集合可能很难绑定。考虑使用数组代替。

相关问题