diff --git a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/JsonKeyValueAdapter.cs b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/JsonKeyValueAdapter.cs index 74d2b882..d353439f 100644 --- a/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/JsonKeyValueAdapter.cs +++ b/src/Microsoft.Extensions.Configuration.AzureAppConfiguration/JsonKeyValueAdapter.cs @@ -15,6 +15,11 @@ namespace Microsoft.Extensions.Configuration.AzureAppConfiguration { internal class JsonKeyValueAdapter : IKeyValueAdapter { + private static readonly JsonDocumentOptions JsonParseOptions = new JsonDocumentOptions + { + CommentHandling = JsonCommentHandling.Skip + }; + public Task>> ProcessKeyValue(ConfigurationSetting setting, Uri endpoint, Logger logger, CancellationToken cancellationToken) { if (setting == null) @@ -28,7 +33,7 @@ public Task>> ProcessKeyValue(Configura try { - using (JsonDocument document = JsonDocument.Parse(rootJson)) + using (JsonDocument document = JsonDocument.Parse(rootJson, JsonParseOptions)) { keyValuePairs = new JsonFlattener().FlattenJson(document.RootElement); } diff --git a/tests/Tests.AzureAppConfiguration/Unit/JsonContentTypeTests.cs b/tests/Tests.AzureAppConfiguration/Unit/JsonContentTypeTests.cs index 91cb03a8..eaca360f 100644 --- a/tests/Tests.AzureAppConfiguration/Unit/JsonContentTypeTests.cs +++ b/tests/Tests.AzureAppConfiguration/Unit/JsonContentTypeTests.cs @@ -276,6 +276,90 @@ public void JsonContentTypeTests_JsonKeyValueAdapterCannotProcessKeyVaultReferen Assert.False(jsonKeyValueAdapter.CanProcess(setting)); } + [Fact] + public void JsonContentTypeTests_LoadJsonValuesWithComments() + { + List _kvCollection = new List + { + // Test various comment styles and positions + ConfigurationModelFactory.ConfigurationSetting( + key: "MixedCommentStyles", + value: @"{ + // Single line comment at start + ""ApiSettings"": { + ""BaseUrl"": ""https://api.example.com"", // Inline single line + /* Multi-line comment + spanning multiple lines */ + ""ApiKey"": ""secret-key"", + ""Endpoints"": [ + // Comment before array element + ""/users"", + /* Comment between elements */ + ""/orders"", + ""/products"" // Comment after element + ] + }, + // Test edge cases + ""StringWithSlashes"": ""This is not a // comment"", + ""StringWithStars"": ""This is not a /* comment */"", + ""UrlValue"": ""https://example.com/path"", // This is a real comment + ""EmptyComment"": ""value"", // + /**/ + ""AfterEmptyComment"": ""value2"" + /* Final multi-line comment */ + }", + contentType: "application/json"), + // Test invalid JSON with comments + ConfigurationModelFactory.ConfigurationSetting( + key: "InvalidJsonWithComments", + value: @"// This is a comment + { invalid json structure + // Another comment + missing quotes and braces", + contentType: "application/json"), + // Test only comments (should be invalid JSON) + ConfigurationModelFactory.ConfigurationSetting( + key: "OnlyComments", + value: @" + // Just comments + /* No actual content */ + ", + contentType: "application/json") + }; + + var mockClientManager = GetMockConfigurationClientManager(_kvCollection); + + var config = new ConfigurationBuilder() + .AddAzureAppConfiguration(options => options.ClientManager = mockClientManager) + .Build(); + + // Verify mixed comment styles are properly parsed + Assert.Equal("https://api.example.com", config["MixedCommentStyles:ApiSettings:BaseUrl"]); + Assert.Equal("secret-key", config["MixedCommentStyles:ApiSettings:ApiKey"]); + Assert.Equal("/users", config["MixedCommentStyles:ApiSettings:Endpoints:0"]); + Assert.Equal("/orders", config["MixedCommentStyles:ApiSettings:Endpoints:1"]); + Assert.Equal("/products", config["MixedCommentStyles:ApiSettings:Endpoints:2"]); + + // Verify edge cases where comment-like text appears in strings + Assert.Equal("This is not a // comment", config["MixedCommentStyles:StringWithSlashes"]); + Assert.Equal("This is not a /* comment */", config["MixedCommentStyles:StringWithStars"]); + Assert.Equal("https://example.com/path", config["MixedCommentStyles:UrlValue"]); + Assert.Equal("value", config["MixedCommentStyles:EmptyComment"]); + Assert.Equal("value2", config["MixedCommentStyles:AfterEmptyComment"]); + + // Invalid JSON should fall back to string value + Assert.Equal(@"// This is a comment + { invalid json structure + // Another comment + missing quotes and braces", config["InvalidJsonWithComments"]); + + // Only comments should be treated as string value (invalid JSON) + Assert.Equal(@" + // Just comments + /* No actual content */ + ", config["OnlyComments"]); + } + private IConfigurationClientManager GetMockConfigurationClientManager(List _kvCollection) { var mockResponse = new Mock();