Answered by:
Json configuration with polymorphic array

Question
-
User-5485716 posted
Is it possible to have a polymorphic array setup by json configuration?
E.g. the following code (all in one file only for the demo of course):
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System.Threading; using System.Threading.Tasks; namespace PolymorphicConfigurationArray { public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { services.Configure<ApplicationOptions>(hostContext.Configuration.GetSection("Application")); services.AddHostedService<Worker>(); }); } public class Worker : BackgroundService { private readonly ILogger<Worker> _logger; public Worker(ILogger<Worker> logger, IOptions<ApplicationOptions> options) { _logger = logger; logger.LogInformation($"Configuration Description {options.Value.Description}"); } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { //_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); await Task.Delay(1000, stoppingToken); } } } public class ApplicationOptions { public string Description { get; set; } public ConfigItem[] Items { get; set; } } public class ConfigItem { public string ItemName { get; set; } } public class ConfigItemWithValue : ConfigItem { public double ItemValue { get; set; } } }
The json file below may be used to intantiate the ApplicationOptions class with some ConfigItems in the Items array, however, I cannot see any way to get the derived ConfigItemWithValue class from configuration and thus having the Items array as a polymorphic array.
Is this simply the limitation of json (key/value)?I know that newtonsoft.json may serialize/deserialize such a graph by some typename options, is this possible to use in any way for configuration (without a lot of custom code of course)
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "Application": { "Description": "Wondering how to achieve polymorphic array with json configuration", "Items": [ { "ItemName": "Name1" }, { "ItemName": "Name2" } ] } }
Monday, June 1, 2020 1:45 PM
Answers
-
User-474980206 posted
while json support arrays of arbitrary objects and typeless languages can load them easily, it is always a struggle with typed languages. There is no native support for this in .net configuration file readers. You can write you own custom mappers, but remember the configuration readers support environment variables, external configuration systems, etc.
as json has only a couple data types: array, string, number and associated array (object), and only string and array of string map directly to C# types, parsing json requires additional information to map to native objects.
it seems like you are implementing a very bad design pattern. .net core encourages strongly typed options.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, June 1, 2020 8:14 PM -
User711641945 posted
Hi EuroEager,
Not sure what is your scenario due to your json file does not contain `ConfigItemWithValue`.If the key and the value are dynamic,I think Bruce's suggestion is correct,just using Dictionary and you could get the key and value.
Best Regards,
Rena
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, June 2, 2020 8:37 AM
All replies
-
User475983607 posted
I think you'll be interested in reading the ASP.NET Core configuration documentation. The documentation covers many way to handler configuration using DI and options.
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1
Monday, June 1, 2020 2:33 PM -
User-474980206 posted
simple. a json mapped object can be mapped to a dictionary:
public class ApplicationOptions { public string Description { get; set; } public Dictionary<string,string> Items { get; set; } }
Monday, June 1, 2020 3:20 PM -
User-5485716 posted
Thanks, but I read both articles several times and cannot find anything regarding polymorphic array
Monday, June 1, 2020 3:23 PM -
User-5485716 posted
Sure, but as far as I can see, that doesn't answer my question about polymorphic array
Monday, June 1, 2020 3:25 PM -
User475983607 posted
Can you explain what you mean by polymorphic array? Polymorphism is an OOP term that refers to objects of difference types can be accessed through a common interface. JSON is not OOP. It is a data format like CSV, fixed width, or XML.
Anyway, see the Options pattern when dealing with configuration; https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-3.1 Keep in mind, this is part of the configuration documentation.
Monday, June 1, 2020 3:57 PM -
User-5485716 posted
I mean an array of say ParentClass objects and some of the instances are of derived types (derived from ParentClass.
I known that json is not about OOP, but e.g. newtonsoft.json may both serialize and deserialize such arrays by adding some extra type information and I just wondered if microsoft,extension.configuration.json had something making this possible as well (without boilerplate code and newtonsoft.json)Monday, June 1, 2020 4:02 PM -
User475983607 posted
I mean an array of say ParentClass objects and some of the instances are of derived types (derived from ParentClass.
I known that json is not about OOP, but e.g. newtonsoft.json may both serialize and deserialize such arrays by adding some extra type information and I just wondered if microsoft,extension.configuration.json had something making this possible as well (without boilerplate code and newtonsoft.json)I still don't get your point. You're mixing inheritance with polymorphism. These are two different OOP concepts. I think Bruce provided the correct solution. Your requirement sounds a lot like a dictionary. Otherwise it sounds like generic which is exactly what you get with the option pattern.
Monday, June 1, 2020 7:13 PM -
User-474980206 posted
while json support arrays of arbitrary objects and typeless languages can load them easily, it is always a struggle with typed languages. There is no native support for this in .net configuration file readers. You can write you own custom mappers, but remember the configuration readers support environment variables, external configuration systems, etc.
as json has only a couple data types: array, string, number and associated array (object), and only string and array of string map directly to C# types, parsing json requires additional information to map to native objects.
it seems like you are implementing a very bad design pattern. .net core encourages strongly typed options.
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Monday, June 1, 2020 8:14 PM -
User-5485716 posted
I think Wikipedia defines polymorphism quite simple:
"The ability in programming to present the same programming interface for differing underlying forms"Inheritance is thus one way of achieving polymorphism as long as the same programming interface is used (the common base class or interface).
Anyway, I have splitted the use of my polymorphic objects into properties of different classes to avoid polymorphism, accepting one of the waeknesses of json for configuration.
Tuesday, June 2, 2020 6:43 AM -
User711641945 posted
Hi EuroEager,
Not sure what is your scenario due to your json file does not contain `ConfigItemWithValue`.If the key and the value are dynamic,I think Bruce's suggestion is correct,just using Dictionary and you could get the key and value.
Best Regards,
Rena
- Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
Tuesday, June 2, 2020 8:37 AM