Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(ConfigurationSetting setting, Uri endpoint, Logger logger, CancellationToken cancellationToken)
{
if (setting == null)
Expand All @@ -28,7 +33,7 @@ public Task<IEnumerable<KeyValuePair<string, string>>> ProcessKeyValue(Configura

try
{
using (JsonDocument document = JsonDocument.Parse(rootJson))
using (JsonDocument document = JsonDocument.Parse(rootJson, JsonParseOptions))
{
keyValuePairs = new JsonFlattener().FlattenJson(document.RootElement);
}
Expand Down
84 changes: 84 additions & 0 deletions tests/Tests.AzureAppConfiguration/Unit/JsonContentTypeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,90 @@ public void JsonContentTypeTests_JsonKeyValueAdapterCannotProcessKeyVaultReferen
Assert.False(jsonKeyValueAdapter.CanProcess(setting));
}

[Fact]
public void JsonContentTypeTests_LoadJsonValuesWithComments()
{
List<ConfigurationSetting> _kvCollection = new List<ConfigurationSetting>
{
// 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<ConfigurationSetting> _kvCollection)
{
var mockResponse = new Mock<Response>();
Expand Down
Loading