4

I have a .Net Core 3.1 console application (not an ASP.NET Core) with SQL Server connection, where connection string is stored in appsettings.json file

{"ConnectionStrings": { "DefaultConnection":"Server=sqlserver;Database=appDb;User=username;Password=password;" }}

Previously I used Json.Net to read a string

var connString = JObject.Parse(File.ReadAllText("appsettings.json")).GetValue("ConnectionStrings").SelectToken("DefaultConnection").ToString()

and it worked fine. Now I decided to switch to System.Text.Json library and having issues with dynamic deserialization. The following code throws an exception:

var dict = JsonSerializer.Deserialize<Dictionary<string, string[]>>("appsettings.json");

System.Text.Json.JsonException: ''a' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.' Inner Exception JsonReaderException: 'a' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.

Then I would read from a dictionary specifying Where Key == "ConnectionStrings", and then subsequent Value of string array == "DefaultConnection". I did not reach that point yet, because of an Exception, so I did not planned how to read from a Dictionary yet.

How can I use a new System.Text.Json library to read a connection string from appsettings.json file? Is it correct to deserialize to Dictianory<string, string[]>? Or it would be better to use Dictianory<string, Dictianory<string, string>>?

Elshad Shabanov
  • 483
  • 10
  • 17
  • Maybe this way is better for you: https://stackoverflow.com/a/40620561/982149 , see also: https://devblogs.microsoft.com/premier-developer/setting-up-net-core-configuration-providers/ – Fildor Mar 03 '20 at 14:26
  • @Fildor it's excellent. Works as charm – Elshad Shabanov Mar 03 '20 at 18:07

3 Answers3

9

JsonSerializer.Deserialize expects a JSON string, not the name of a file.

You need to load the file into a string and then pass that to the Deserialize method:

var json = File.ReadAllText("appsettings.json");
var dict = JsonSerializer.Deserialize<Dictionary<string, string[]>>(json);
Sean
  • 60,939
  • 11
  • 97
  • 136
3

One of the benefits of System.Text.Json is that it can easily and efficiently deserialize directly from a Stream. When reading JSON from I/O such as a file or HTTP request, it's better to just deserialize the Stream directly and avoid the unnecessary allocations and memory required to read it into a string first.

using var reader = new StreamReader("appsettings.json");
var dict = await JsonSerializer.DeserializeAsync<<Dictionary<string, string[]>>(reader.BaseStream);

That being said, for the specific case of reading the appsettings.json, it's better to use the configuration tools built-in to the .NET Generic Host instead of manually parsing the JSON. This gives added benefits such as the ability to override these settings using environment variables and/or command line switches, as well as more easily moving them to another storage system such as KeyVault.

Tobias J
  • 19,813
  • 8
  • 81
  • 66
1

I've used the api in JsonDocument for this purpose:

var json = File.ReadAllText("appsettings.json");
var appSettings = JsonDocument.Parse(json, new JsonDocumentOptions { CommentHandling = JsonCommentHandling.Skip });
var result = appSettings.RootElement.GetProperty("ConnectionStrings").GetProperty("DefaultConnection").GetString();  

HTH

ashilon
  • 1,791
  • 3
  • 24
  • 41