LWChris
LWChris

Reputation: 4201

How to distinguish empty/null/unset array property in appsettings.json?

I am using Microsoft.Extensions.Configuration in ASP.NET Core 9.0 to access configurations from the appsettings.json file:

public class MySettings
{
    public int? Foo { get; set; }
    public string[]? Bar{ get; set; }
}

appsettings.json:

{
    [...]
    "MySettings": {
        "Foo": 42,
        "Bar": [
            "a",
            "b",
            "c"
        ]
    }
}

I'm reading this part this way:

var mySettings = config.GetSection("MySettings").Get<MySettings>();

This works well, mySettings.Bar is string[3] = ["a", "b", "c"] as you'd expect.

Now I'm having trouble to distinguish between three other cases in appsettings.json:

A:

{
    [...]
    "MySettings": {
        "Foo": 42
    }
}

B:

{
    [...]
    "MySettings": {
        "Foo": 42,
        "Bar": null
    }
}

C:

{
    [...]
    "MySettings": {
        "Foo": 42,
        "Bar": []
    }
}

For all three cases, mySettings.Bar will become null, but I'd want only A and B to become null, and C to become string[0].

I have found lots of little bits and ideas from a question for Newtonsoft Json.NET but I can't seem to figure out how to cram it all into something that works with Microsoft.Extensions.Configuration:

It is crucial for me to be able to differentiate between A and C. B should preferably become null since that's what the file says, but I could cope with that becoming string[0] as well, too.

Upvotes: 2

Views: 138

Answers (1)

pfx
pfx

Reputation: 23234

Appsettings are not being handled by json (de)serialization, but by the JsonConfigurationFileParser which uses custom parsing.

This JsonConfigurationFileParser has private built-in logic to set empty arrays to null; see source code on GitHub.


A possible solution to achieve your goal is to inspect the MySettings configuration section as a Dictionary<string, object>. When applicable, adjust the value of the Bar property on the mySettings instance returned from below statement that you are already using.

var mySettings = config.GetSection("MySettings").Get<MySettings>();
  • For scenario A, the TryGetValue method of the dictionary will return false.
  • For scenario B, the dictionary holds an empty string value for key Bar. This is also a rather unexpected behavior of the JsonConfigurationFileParser.

scenario B

  • For scenario C, the value for dictionary entry with key Bar is null.

scenario C

That gives below code, which checks whether the Bar key is present and whether the value is not an empty string. If so, either an array with values or an empty one has been configured and a possible nullvalue for property Bar needs to be replaced by an empty array.

var mySettings = config.GetSection("MySettings").Get<MySettings>();

var section = config.GetRequiredSection("MySettings").Get<Dictionary<string, object>>()!;
if (section.TryGetValue("Bar", out var value)
    && value is not string
    )
{
    mySettings.Bar ??= [];
}

Upvotes: 2

Related Questions