Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customize JSON property name for options in ASP.NET Core

I want to use different property names for configuration, when loading the configuration from a JSON file.

public class MinioConfiguration
{
    [DataMember(Name = "MINIO_ENDPOINT")]
    public string Endpoint { get; set; }
    [DataMember(Name = "MINIO_ACCESS_KEY")]
    public string AccessKey { get; set; }
    [DataMember(Name = "MINIO_SECRET_KEY")]
    public string SecretKey { get; set; }
}

Neither DataMember nor JsonProperty work. Is there a possibility to achieve it?

like image 336
Ondrej Tomcik Avatar asked Aug 24 '17 08:08

Ondrej Tomcik


People also ask

What is property name in JSON?

In JSON, the “keys” must always be strings. Each of these pairs is conventionally referred to as a “property”.

What does Jsonconvert DeserializeObject do?

DeserializeObject Method. Deserializes the JSON to a . NET object.


2 Answers

This is unfortunately not possible. The responsible components here are the JSON configuration provider (Microsoft.Extensions.Configuration.Json) and the configuration binder (Microsoft.Extensions.Configuration.Binder). The former is responsible for loading the JSON file into an IConfiguration, while the latter’s job is to map an IConfiguration into a type.

The configuration binder however is source agnostic, so it does not care where the configuration came from, whether that being JSON, an in-memory configuration or environment variables. So the binder, by design, cannot look for source-specific attributes on the target type.

On the other hand, configurations are not guaranteed to be bound to any type, so the configuration provider needs to work consistently regardless of whether it binds to a type or not. So the JSON provider follows its own conventions to map JSON properties to configuration keys.

Since both components run independently—the binder running even explicitly on the IConfiguration object, so it runs much later than the actual configuration parsing process—they cannot communicate and share information. So it’s simply not possible for the JSON configuration provider to access the information, the binder much later gets about the target type. As such, you simply cannot change the configuration names.

However, I would argue that this is not something that should be done anyway. The configuration is a very application-specific thing, but if you want to use different keys that looks like you want to use a configuration file that is not necessarily owned by the application. I would recommend against this approach and rather use an application-specific configuration file.

If you need to reuse that configuration file, you could always write your own configuration provider for that specific type. Writing a configuration provider is not that difficult, especially when you are going to restrict it to a very specific format anyway.

like image 192
poke Avatar answered Sep 25 '22 20:09

poke


In case someone run into this.

Here's old hack for it:

  public class ServiceConfig
  {
    private string web_internal
    {
      // Note it does not work without this noop getter
      get => "it's hack for Microsoft.Configuration.Binder";
      set => WebInternal = value;
    }

    public string WebInternal { get; set; }
  }

Then where you want to bind it

var serviceConfig = config.Get<ServiceConfig>(o => o.BindNonPublicProperties = true);

Though I think Microsoft should add support to override names.

It's not about that relations with ConfigurationSource's, it's about ConfigurationBinder itself - if it sees that property has DataMember attribute then it should use it instead of property name for the key.

like image 20
Veikedo Avatar answered Sep 25 '22 20:09

Veikedo