-
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: add key value pair json encoder
- Loading branch information
Showing
5 changed files
with
205 additions
and
2 deletions.
There are no files selected for viewing
11 changes: 11 additions & 0 deletions
11
src/AzureAppConfigurationEmulator/Common/IKeyValuePairJsonEncoder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using System.Text.Json; | ||
|
||
namespace AzureAppConfigurationEmulator.Common; | ||
|
||
public interface IKeyValuePairJsonEncoder | ||
{ | ||
JsonDocument Encode( | ||
IEnumerable<KeyValuePair<string, string?>> pairs, | ||
string? prefix = null, | ||
string? separator = null); | ||
} |
90 changes: 90 additions & 0 deletions
90
src/AzureAppConfigurationEmulator/Common/KeyValuePairJsonEncoder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
using System.Text.Json; | ||
using System.Text.Json.Nodes; | ||
|
||
namespace AzureAppConfigurationEmulator.Common; | ||
|
||
public class KeyValuePairJsonEncoder : IKeyValuePairJsonEncoder | ||
{ | ||
public JsonDocument Encode( | ||
IEnumerable<KeyValuePair<string, string?>> pairs, | ||
string? prefix = null, | ||
string? separator = null) | ||
{ | ||
JsonNode root = new JsonObject(); | ||
|
||
foreach (var (key, value) in pairs) | ||
{ | ||
var keys = key.Split(separator).ToList(); | ||
|
||
if (!string.IsNullOrEmpty(prefix)) | ||
{ | ||
if (keys[0] == prefix) | ||
{ | ||
keys.RemoveAt(0); | ||
} | ||
else if (keys[0].StartsWith(prefix)) | ||
{ | ||
keys[0] = keys[0][prefix.Length..]; | ||
} | ||
} | ||
|
||
var current = root; | ||
|
||
for (var i = 0; i < keys.Count; i++) | ||
{ | ||
if (int.TryParse(keys[i], out var index)) | ||
{ | ||
if (i == keys.Count - 1) | ||
{ | ||
current.AsArray().Insert(index, value); | ||
|
||
break; | ||
} | ||
|
||
if (current.AsArray().ElementAtOrDefault(index) is not { } next) | ||
{ | ||
if (int.TryParse(keys[i + 1], out _)) | ||
{ | ||
next = new JsonArray(); | ||
} | ||
else | ||
{ | ||
next = new JsonObject(); | ||
} | ||
|
||
current.AsArray().Insert(index, next); | ||
} | ||
|
||
current = next; | ||
} | ||
else | ||
{ | ||
if (i == keys.Count - 1) | ||
{ | ||
current[keys[i]] = value; | ||
|
||
break; | ||
} | ||
|
||
if (current[keys[i]] is not { } next) | ||
{ | ||
if (int.TryParse(keys[i + 1], out _)) | ||
{ | ||
next = new JsonArray(); | ||
} | ||
else | ||
{ | ||
next = new JsonObject(); | ||
} | ||
|
||
current[keys[i]] = next; | ||
} | ||
|
||
current = next; | ||
} | ||
} | ||
} | ||
|
||
return root.Deserialize<JsonDocument>()!; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
tests/AzureAppConfigurationEmulator.Tests/Common/KeyValuePairJsonEncoderTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
using System.Text.Json; | ||
using AzureAppConfigurationEmulator.Common; | ||
using NUnit.Framework; | ||
|
||
namespace AzureAppConfigurationEmulator.Tests.Common; | ||
|
||
public class KeyValuePairJsonEncoderTests | ||
{ | ||
private KeyValuePairJsonEncoder Encoder { get; set; } | ||
|
||
[SetUp] | ||
public void SetUp() | ||
{ | ||
Encoder = new KeyValuePairJsonEncoder(); | ||
} | ||
|
||
[TestCaseSource(nameof(Encode_Document_KeyValuePairsAndPrefixAndSeparator_TestCases))] | ||
public void Encode_Document_KeyValuePairsAndPrefixAndSeparator(IEnumerable<KeyValuePair<string, string?>> pairs, string? prefix, string? separator, string expected) | ||
{ | ||
// Act | ||
using var document = Encoder.Encode(pairs, prefix, separator); | ||
|
||
// Assert | ||
Assert.That(JsonSerializer.Serialize(document), Is.EqualTo(expected)); | ||
} | ||
|
||
// ReSharper disable once InconsistentNaming | ||
private static object[] Encode_Document_KeyValuePairsAndPrefixAndSeparator_TestCases = | ||
[ | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestKey", "TestValue" } }, | ||
null, | ||
null, | ||
"{\"TestKey\":\"TestValue\"}" | ||
}, | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestPrefixTestKey", "TestValue" } }, | ||
"TestPrefix", | ||
null, | ||
"{\"TestKey\":\"TestValue\"}" | ||
}, | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestKey", "TestValue" } }, | ||
null, | ||
".", | ||
"{\"TestKey\":\"TestValue\"}" | ||
}, | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestPrefix.TestKey", "TestValue" } }, | ||
"TestPrefix", | ||
".", | ||
"{\"TestKey\":\"TestValue\"}" | ||
}, | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestOuterKey.TestInnerKey", "TestValue" } }, | ||
null, | ||
".", | ||
"{\"TestOuterKey\":{\"TestInnerKey\":\"TestValue\"}}" | ||
}, | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestPrefix.TestOuterKey.TestInnerKey", "TestValue" } }, | ||
"TestPrefix", | ||
".", | ||
"{\"TestOuterKey\":{\"TestInnerKey\":\"TestValue\"}}" | ||
}, | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestKey.0", "TestValue" } }, | ||
null, | ||
".", | ||
"{\"TestKey\":[\"TestValue\"]}" | ||
}, | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestPrefix.TestKey.0", "TestValue" } }, | ||
"TestPrefix", | ||
".", | ||
"{\"TestKey\":[\"TestValue\"]}" | ||
}, | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestOuterKey.0.TestInnerKey", "TestValue" } }, | ||
null, | ||
".", | ||
"{\"TestOuterKey\":[{\"TestInnerKey\":\"TestValue\"}]}" | ||
}, | ||
new object?[] | ||
{ | ||
new Dictionary<string, string?> { { "TestPrefix.TestOuterKey.0.TestInnerKey", "TestValue" } }, | ||
"TestPrefix", | ||
".", | ||
"{\"TestOuterKey\":[{\"TestInnerKey\":\"TestValue\"}]}" | ||
} | ||
]; | ||
} |