【问题标题】:ASP.NET Core Get Json Array using IConfigurationASP.NET Core 使用 IConfiguration 获取 Json 数组
【发布时间】:2017-05-10 19:00:59
【问题描述】:

在 appsettings.json 中

{
      "MyArray": [
          "str1",
          "str2",
          "str3"
      ]
}

在 Startup.cs 中

public void ConfigureServices(IServiceCollection services)
{
     services.AddSingleton<IConfiguration>(Configuration);
}

在 HomeController 中

public class HomeController : Controller
{
    private readonly IConfiguration _config;
    public HomeController(IConfiguration config)
    {
        this._config = config;
    }

    public IActionResult Index()
    {
        return Json(_config.GetSection("MyArray"));
    }
}

上面有我的代码,我得到了 null 如何获取数组?

【问题讨论】:

    标签: c# asp.net-core asp.net-core-mvc


    【解决方案1】:

    您可以安装以下两个 NuGet 包:

    using Microsoft.Extensions.Configuration; 
    using Microsoft.Extensions.Configuration.Binder;
    

    然后您将有可能使用以下扩展方法:

    var myArray = _config.GetSection("MyArray").Get<string[]>();
    

    【讨论】:

    • 这比其他答案更直接。
    • 这是迄今为止最好的答案。
    • 就我而言,Aspnet core 2.1 web 应用程序包含这两个 nuget 包。所以它只是一个换行符。谢谢
    • 它也适用于对象数组,例如_config.GetSection("AppUser").Get&lt;AppUser[]&gt;();
    • 我想知道为什么他们不能通过简单地使用GetValue 来使其工作:Configuration.GetValue&lt;string[]&gt;("MyArray")。
    【解决方案2】:

    如果您想选择第一项的价值,那么您应该这样做-

    var item0 = _config.GetSection("MyArray:0");
    

    如果你想选择整个数组的值,那么你应该这样做-

    IConfigurationSection myArraySection = _config.GetSection("MyArray");
    var itemArray = myArraySection.AsEnumerable();
    

    理想情况下,您应该考虑使用官方文档建议的options pattern。这将为您带来更多好处。

    【讨论】:

    • 如果你有一个像"Clients": [ {..}, {..} ]这样的对象数组,你应该调用Configuration.GetSection("Clients").GetChildren()。
    • 如果你有一个像"Clients": [ "", "", "" ]这样的字面量数组,你应该调用.GetSection("Clients").GetChildren().ToArray().Select(c =&gt; c.Value).ToArray()。
    • 这个答案实际上会产生 4 个项目,第一个是具有空值的部分本身。这是不正确的。
    • 我成功调用它是这样的:var clients = Configuration.GetSection("Clients").GetChildren() .Select(clientConfig =&gt; new Client { ClientId = clientConfig["ClientId"], ClientName = clientConfig["ClientName"], ... }) .ToArray();
    • 这些选项对我都不起作用,因为对象在“客户”处返回空值,使用 halo 的示例。我相信 json 格式正确,因为它可以使用格式为 "Item":[{...},{...}] 的字符串 ["item:0:childItem"] 中插入的偏移量
    【解决方案3】:

    在您的 appsettings.json 中添加一个级别:

    {
      "MySettings": {
        "MyArray": [
          "str1",
          "str2",
          "str3"
        ]
      }
    }
    

    创建一个代表你的部分的类:

    public class MySettings
    {
         public List<string> MyArray {get; set;}
    }
    

    在您的应用程序启动类中,绑定您的模型并将其注入 DI 服务:

    services.Configure<MySettings>(options => Configuration.GetSection("MySettings").Bind(options));
    

    在您的控制器中,从 DI 服务获取您的配置数据:

    public class HomeController : Controller
    {
        private readonly List<string> _myArray;
    
        public HomeController(IOptions<MySettings> mySettings)
        {
            _myArray = mySettings.Value.MyArray;
        }
    
        public IActionResult Index()
        {
            return Json(_myArray);
        }
    }
    

    如果您需要所有数据,您还可以将整个配置模型存储在控制器的属性中:

    public class HomeController : Controller
    {
        private readonly MySettings _mySettings;
    
        public HomeController(IOptions<MySettings> mySettings)
        {
            _mySettings = mySettings.Value;
        }
    
        public IActionResult Index()
        {
            return Json(_mySettings.MyArray);
        }
    }
    

    ASP.NET Core 的依赖注入服务就像一个魅力:)

    【讨论】:

    • 我收到一个错误,它需要在“MySettings”和“MyArray”之间使用逗号。
    • 感谢您的信息。我相信这最好地回答了最初的问题。
    • 如果不是简单的字符串数组而是数组数组怎么办?例如这个报告定义数组,我想为每个报告检索cols 数组:"reports": [ {"name":"reportA", "id": "1", "cols": [{"order":"1","name":"empid"},{"order":"2","name":"firstname"}]}, {"name":"reportB", "id": "2"}, "cols": [{"order":"1","name":"typeID"},{"order":"2","name":"description"}]]
    【解决方案4】:

    如果您有这样的复杂 JSON 对象数组:

    {
      "MySettings": {
        "MyValues": [
          { "Key": "Key1", "Value":  "Value1" },
          { "Key": "Key2", "Value":  "Value2" }
        ]
      }
    }
    

    您可以通过这种方式检索设置:

    var valuesSection = configuration.GetSection("MySettings:MyValues");
    foreach (IConfigurationSection section in valuesSection.GetChildren())
    {
        var key = section.GetValue<string>("Key");
        var value = section.GetValue<string>("Value");
    }
    

    【讨论】:

    • 正是我要找的东西,像魅力一样工作,谢谢!
    • 简单明了!
    【解决方案5】:

    这对我来说可以从我的配置中返回一个字符串数组:

    var allowedMethods = Configuration.GetSection("AppSettings:CORS-Settings:Allow-Methods")
        .Get<string[]>();
    

    我的配置部分如下所示:

    "AppSettings": {
        "CORS-Settings": {
            "Allow-Origins": [ "http://localhost:8000" ],
            "Allow-Methods": [ "OPTIONS","GET","HEAD","POST","PUT","DELETE" ]
        }
    }
    

    【讨论】:

      【解决方案6】:

      对于从配置中返回复杂 JSON 对象数组的情况,我已调整 @djangojazz's answer 以使用匿名类型和动态而不是元组。

      给定一个设置部分:

      "TestUsers": [
      {
        "UserName": "TestUser",
        "Email": "Test@place.com",
        "Password": "P@ssw0rd!"
      },
      {
        "UserName": "TestUser2",
        "Email": "Test2@place.com",
        "Password": "P@ssw0rd!"
      }],
      

      你可以这样返回对象数组:

      public dynamic GetTestUsers()
      {
          var testUsers = Configuration.GetSection("TestUsers")
                          .GetChildren()
                          .ToList()
                          .Select(x => new {
                              UserName = x.GetValue<string>("UserName"),
                              Email = x.GetValue<string>("Email"),
                              Password = x.GetValue<string>("Password")
                          });
      
          return new { Data = testUsers };
      }
      

      【讨论】:

      • 这太棒了
      • 你的答案很完美。
      【解决方案7】:

      DotNet Core 3.1:

      Json 配置:

      "TestUsers": 
      {
          "User": [
          {
            "UserName": "TestUser",
            "Email": "Test@place.com",
            "Password": "P@ssw0rd!"
          },
          {
            "UserName": "TestUser2",
            "Email": "Test2@place.com",
            "Password": "P@ssw0rd!"
          }]
      }
      

      然后创建一个具有自动属性的 User.cs 类,该类对应于上面 Json 配置中的 User 对象。然后您可以参考 Microsoft.Extensions.Configuration.Abstractions 并执行以下操作:

      List<User> myTestUsers = Config.GetSection("TestUsers").GetSection("User").Get<List<User>>();
      

      【讨论】:

        【解决方案8】:

        在 ASP.NET Core 2.2 及更高版本中,我们可以在应用程序的任何位置注入 IConfiguration 就像你的情况一样,你可以在 HomeController 中注入 IConfiguration 并像这样使用来获取数组。

        string[] array = _config.GetSection("MyArray").Get<string[]>();
        

        【讨论】:

          【解决方案9】:

          有点老问题,但我可以给出一个针对具有 C# 7 标准的 .NET Core 2.1 更新的答案。假设我只有在 appsettings.Development.json 中有一个列表,例如:

          "TestUsers": [
            {
              "UserName": "TestUser",
              "Email": "Test@place.com",
              "Password": "P@ssw0rd!"
            },
            {
              "UserName": "TestUser2",
              "Email": "Test2@place.com",
              "Password": "P@ssw0rd!"
            }
          ]
          

          我可以在 Microsoft.Extensions.Configuration.IConfiguration 实现和连接的任何地方提取它们,如下所示:

          var testUsers = Configuration.GetSection("TestUsers")
             .GetChildren()
             .ToList()
              //Named tuple returns, new in C# 7
             .Select(x => 
                   (
                    x.GetValue<string>("UserName"), 
                    x.GetValue<string>("Email"), 
                    x.GetValue<string>("Password")
                    )
              )
              .ToList<(string UserName, string Email, string Password)>();
          

          现在我有一个类型良好的对象列表。如果我使用 testUsers.First(),Visual Studio 现在应该显示“用户名”、“电子邮件”和“密码”选项。

          【讨论】:

            【解决方案10】:

            您可以直接获取数组,而无需在配置中增加新级别:

            public void ConfigureServices(IServiceCollection services) {
                services.Configure<List<String>>(Configuration.GetSection("MyArray"));
                //...
            }
            

            【讨论】:

              【解决方案11】:

              这对我有用; 创建一些 json 文件:

              {
                  "keyGroups": [
                      {
                          "Name": "group1",
                          "keys": [
                              "user3",
                              "user4"
                          ]
                      },
                      {
                          "Name": "feature2And3",
                          "keys": [
                              "user3",
                              "user4"
                          ]
                      },
                      {
                          "Name": "feature5Group",
                          "keys": [
                              "user5"
                          ]
                      }
                  ]
              }
              

              然后,定义一些映射的类:

              public class KeyGroup
              {
                  public string name { get; set; }
                  public List<String> keys { get; set; }
              }
              

              nuget 包:

              Microsoft.Extentions.Configuration.Binder 3.1.3
              Microsoft.Extentions.Configuration 3.1.3
              Microsoft.Extentions.Configuration.json 3.1.3
              

              然后,加载它:

              using Microsoft.Extensions.Configuration;
              using System.Linq;
              using System.Collections.Generic;
              
              ConfigurationBuilder configurationBuilder = new ConfigurationBuilder();
              
              configurationBuilder.AddJsonFile("keygroup.json", optional: true, reloadOnChange: true);
              
              IConfigurationRoot config = configurationBuilder.Build();
              
              var sectionKeyGroups = 
              config.GetSection("keyGroups");
              List<KeyGroup> keyGroups = 
              sectionKeyGroups.Get<List<KeyGroup>>();
              
              Dictionary<String, KeyGroup> dict = 
                          keyGroups = keyGroups.ToDictionary(kg => kg.name, kg => kg);
              

              【讨论】:

                【解决方案12】:

                短格式:

                var myArray= configuration.GetSection("MyArray")
                                        .AsEnumerable()
                                        .Where(p => p.Value != null)
                                        .Select(p => p.Value)
                                        .ToArray();
                

                它返回一个字符串数组:

                {"str1","str2","str3"}

                【讨论】:

                • 为我工作。谢谢。使用 Microsoft.Extensions.Configuration.Binder 也可以,但是如果一行代码可以完成这项工作,我想避免引用另一个 Nuget 包。
                • 谢谢 这个答案正确处理了值为空数组的情况,如MyArray: []
                【解决方案13】:
                public class MyArray : List<string> { }
                
                services.Configure<ShipmentDetailsDisplayGidRoles>(Configuration.GetSection("MyArray"));
                
                public SomeController(IOptions<MyArray> myArrayOptions)
                {
                    myArray = myArrayOptions.Value;
                }
                

                【讨论】:

                  【解决方案14】:

                  appsettings.json:

                  "MySetting": {
                    "MyValues": [
                      "C#",
                      "ASP.NET",
                      "SQL"
                    ]
                  },
                  

                  MySetting 类:

                  namespace AspNetCore.API.Models
                  {
                      public class MySetting : IMySetting
                      {
                          public string[] MyValues { get; set; }
                      }
                  
                      public interface IMySetting
                      {
                          string[] MyValues { get; set; }
                      }
                  }
                  

                  Startup.cs

                  public void ConfigureServices(IServiceCollection services)
                  {
                      ...
                      services.Configure<MySetting>(Configuration.GetSection(nameof(MySetting)));
                      services.AddSingleton<IMySetting>(sp => sp.GetRequiredService<IOptions<MySetting>>().Value);
                      ...
                  }
                  

                  Controller.cs

                  public class DynamicController : ControllerBase
                  {
                      private readonly IMySetting _mySetting;
                  
                      public DynamicController(IMySetting mySetting)
                      {
                          this._mySetting = mySetting;
                      }
                  }
                  

                  访问值:

                  var myValues = this._mySetting.MyValues;
                  

                  【讨论】:

                  • 这看起来是正确的。但是选项模式(微软称之为)不需要选项类中的接口。您可以通过注入 IOptions&lt;T&gt; 而不是添加单例的开销来获得您的选择。
                  【解决方案15】:

                  从appsettings.json获取所有部分的所有值

                          public static string[] Sections = { "LogDirectory", "Application", "Email" };
                          Dictionary<string, string> sectionDictionary = new Dictionary<string, string>();
                  
                          List<string> sectionNames = new List<string>(Sections);
                          
                          sectionNames.ForEach(section =>
                          {
                              List<KeyValuePair<string, string>> sectionValues = configuration.GetSection(section)
                                      .AsEnumerable()
                                      .Where(p => p.Value != null)
                                      .ToList();
                              foreach (var subSection in sectionValues)
                              {
                                  sectionDictionary.Add(subSection.Key, subSection.Value);
                              }
                          });
                          return sectionDictionary;
                  

                  【讨论】:

                    【解决方案16】:

                    setting.json 文件:

                    {
                        "AppSetting": {
                            "ProfileDirectory": "C:/Users/",
                            "Database": {
                                "Port": 7002
                            },
                            "Backend": {
                                "RunAsAdmin": true,
                                "InstallAsService": true,
                                "Urls": [
                                    "http://127.0.0.1:8000"
                                ],
                                "Port": 8000,
                                "ServiceName": "xxxxx"
                            }
                        }
                    }
                    

                    代码

                    代码:

                    public static IConfigurationRoot GetConfigurationFromArgs(string[] args, string cfgDir)
                    {
                        var builder = new ConfigurationBuilder()
                                .SetBasePath(cfgDir)
                                .AddCommandLine(args ?? new string[0]) // null  in UnitTest null will cause exception
                                .AddJsonFile(Path.Combine(cfgDir, "setting.json"), optional: true, reloadOnChange: true)
                                .AddEnvironmentVariables()
                            // .AddInMemoryollection(configDictionary)
                            ;
                        var config = builder.Build();
                        return config;
                    }
                    

                    你可以使用services.AddOptions&lt;AppSettingOption&gt;("AppSetting")或者直接从IConfigurationRoot 对象中获取Object。

                    var cfg = GetConfigurationFromArgs(args, appDataDirectory);
                    cfg.GetSection("AppSetting").Get<AppSettingOption>()
                    

                    输出:

                    {App.AppSettingOption}
                        Backend: {App.BackendOption}
                        Database: {App.DatabaseOption}
                        ProfileDirectory: "C:/Users/"
                    

                    【讨论】:

                      【解决方案17】:

                      您可以像这样使用Microsoft.Extensions.Configuration.Binder 包:

                      在你的appsettings.json

                      {
                            "MyArray": [
                                "str1",
                                "str2",
                                "str3"
                            ]
                      }
                      

                      创建你的对象来保存你的配置:

                       public class MyConfig
                       {
                           public List<string> MyArray { get; set; }
                       }
                      

                      在你的控制器Bind 中配置:

                      public class HomeController : Controller
                      {
                          private readonly IConfiguration _config;
                          private readonly MyConfig _myConfig = new MyConfig();
                      
                          public HomeController(IConfiguration config)
                          {
                              this._config = config;
                          }
                      
                          public IActionResult Index()
                          {
                              return Json(_config.Bind(_myConfig));
                          }
                      }
                      

                      【讨论】:

                        【解决方案18】:

                        最近我还需要从appsettings.json 文件(和其他类似的.json 配置文件)中读取一个简单的字符串数组。

                        对于我的方法,我创建了一个简单的扩展方法来解决问题:

                        public static class IConfigurationRootExtensions
                        {
                            public static string[] GetArray(this IConfigurationRoot configuration, string key)
                            {
                                var collection = new List<string>();
                                var children = configuration.GetSection(key)?.GetChildren();
                                if (children != null)
                                {
                                    foreach (var child in children) collection.Add(child.Value);
                                }
                                return collection.ToArray();
                            }
                        }
                        

                        原海报的.json文件如下:

                        {
                              "MyArray": [
                                  "str1",
                                  "str2",
                                  "str3"
                              ]
                        }
                        

                        使用上面的扩展方法,使得读取这个数组变得非常简单的一行代码,如下例所示:

                        var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
                        string[] values = configuration.GetArray("MyArray");
                        

                        在运行时,在values 上设置一个带有“QuickWatch”的断点来验证我们已经成功地将.json 配置文件中的值读入一个字符串数组:

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2018-06-09
                          • 1970-01-01
                          • 1970-01-01
                          • 2018-01-26
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多