【问题标题】:Reading a JSON object from appsettings.json从 appsettings.json 读取 JSON 对象
【发布时间】:2018-08-02 16:43:41
【问题描述】:

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

我有一个具有多种配置值类型的 .NET Core 2.x 应用程序。 appsettings.json 看起来像下面的 sn-p,我正在尝试将 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") 毫无问题地读取简单的配置值(键:值对)。

Configuration.GetSection Configuration.GetSection("ElasticSearch:MyIndex:mappings").Value 为我提供了 nullValue 值。

Configuration.GetValue Configuration.GetValue<string>("ElasticSearch:MyIndex:mappings") 也返回一个空值。这对我来说很有意义,因为根据上述尝试,该部分具有空值。

Configuration.GetValue Configuration.GetValue<JToken>("ElasticSearch:MyIndex:mappings") 也返回一个空值。出于与上述相同的原因,这对我来说也很有意义。

【问题讨论】:

  • 这只是一个错字吗?您的密钥中有一个双 ::...
  • @DavidG 是的,这是我的示例中的一种类型,在我的代码中没有出现。现在修复它。
  • 另外,您不能在复杂对象上调用 .Value,这仅适用于 string 值。
  • 我正在尝试任何我能想到的东西,看看它是否会起作用或帮助我找出其他解决方案。我已经能够通过将 appsettings.json 作为 JSON 文件读取并获取我需要的对象来使其工作。
  • 我可以通过直接解析appsettings.json 并读取我需要的属性来解决问题。但我还是想看看有没有其他选择。

标签: json .net-core configuration-files


【解决方案1】:
Dictionary<string,object> settings = Configuration
    .GetSection("ElasticSearch")
    .Get<Dictionary<string,object>>();
string json = JsonConvert.SerializeObject(settings);

【讨论】:

  • .Get>();缺少右括号
  • 虽然我希望它能够工作,但它会引发我无法解决的异常。有小费吗?也许它现在在 .NET Core 3.1 中的工作方式有所不同。 System.ArgumentNullException:值不能为空。 System.Reflection.IntrospectionExtensions.GetTypeInfo(Type type) 处的(参数“类型”)
  • 我不确定,你有没有仔细检查过 Configuration 有一个有自己的孩子的孩子“ElasticSearch”?
【解决方案2】:

解决方案最终比我最初尝试的任何方法都简单得多:将 appsettings.json 作为任何其他 JSON 格式文件读取。

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

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

【讨论】:

  • 什么是 JToken?你从哪里得到那个的? @babak-naffas
  • 这种方法有很多问题。如果您的设置被其他提供商覆盖,那么除非您遵循 chris 的回答,否则您将不会获得更新的值。
  • @It'satrap 两种解决方案最终都会在读取配置值时的某个时间点拍摄配置值的快照。我承认你的观点是 IConfiguration 引用本身被注入到依赖项中。
【解决方案3】:

将您的 JSON 对象转换为转义字符串。为此,您很可能只需要转义所有双引号并将其放在 一行 上,因此它看起来像:

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

然后您可以将其读入一个字符串,只需使用即可解析:

Configuration["ElasticSearch"]

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

【讨论】:

    【解决方案4】:

    @chris313​​89 的解决方案很好,并收到了我的投票。但是,我的情况需要更通用的解决方案。

    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.Binder`
    • 正如上面提到的@chris313​​89,您必须反序列化为字典,然后重新序列化为字符串,否则您将获得空值。这行不通
      configuration
        .GetSection(key)
        .Get<TConfig>()
      
    • 如果您尝试反序列化一个数组,则需要一个`Dictionary[]`。这就是为什么其他解决方案有时不起作用的原因。

    【讨论】:

      【解决方案5】:

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

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

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

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

      【讨论】:

        【解决方案6】:

        读取配置:

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

        然后您可以创建一个映射 JSON 文件(或其中一部分)结构的 POCO。 例如,如果类名是 ConnectionStringsConfiguration

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

        然后使用:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-03-06
          • 1970-01-01
          • 2021-11-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-10
          • 2019-07-06
          相关资源
          最近更新 更多