Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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 @@ -26,9 +26,11 @@ public static partial class ConfigurationPath
public static readonly string KeyDelimiter;
public static string Combine(System.Collections.Generic.IEnumerable<string> pathSegments) { throw null; }
public static string Combine(params string[] pathSegments) { throw null; }
public static string CombineWith(string separator, params string[] pathSegments) { throw null; }
public static string? GetParentPath(string? path) { throw null; }
[return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("path")]
public static string? GetSectionKey(string? path) { throw null; }
public static string? GetSectionKeyWith(string separator, string? path) { throw null; }
}
public static partial class ConfigurationRootExtensions
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public static string Combine(params string[] pathSegments!!)
return string.Join(KeyDelimiter, pathSegments);
}

public static string CombineWith(string separator, params string[] pathSegments!!)
{
return string.Join(separator, pathSegments);
}

/// <summary>
/// Combines path segments into one path.
/// </summary>
Expand Down Expand Up @@ -54,6 +59,24 @@ public static string Combine(IEnumerable<string> pathSegments!!)
return lastDelimiterIndex == -1 ? path : path.Substring(lastDelimiterIndex + 1);
}

/// <summary>
/// Extracts the last path segment from the path.
/// </summary>
/// <param name="separator"></param>
/// <param name="path">The path.</param>
/// <returns>The last path segment of the path.</returns>
[return: NotNullIfNotNull("path")]
public static string? GetSectionKeyWith(string separator, string? path)
{
if (string.IsNullOrEmpty(path))
{
return path;
}

int lastDelimiterIndex = path.LastIndexOf(separator, StringComparison.OrdinalIgnoreCase);
return lastDelimiterIndex == -1 ? path : path.Substring(lastDelimiterIndex + 1);
}

/// <summary>
/// Extracts the path corresponding to the parent node for a given path.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,31 @@ namespace Microsoft.Extensions.Configuration
public static partial class JsonConfigurationExtensions
{
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, Microsoft.Extensions.FileProviders.IFileProvider? provider, string path, bool optional, bool reloadOnChange) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, Microsoft.Extensions.FileProviders.IFileProvider? provider, string path, bool optional, bool reloadOnChange, string separator = ":") { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.Action<Microsoft.Extensions.Configuration.Json.JsonConfigurationSource>? configureSource) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, string path) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, string path, bool optional) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange, string separator) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, string path, bool optional, string separator) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonFile(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, string path, string separator) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonStream(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.IO.Stream stream) { throw null; }
public static Microsoft.Extensions.Configuration.IConfigurationBuilder AddJsonStream(this Microsoft.Extensions.Configuration.IConfigurationBuilder builder, System.IO.Stream stream, string separator = ":") { throw null; }
}
}
namespace Microsoft.Extensions.Configuration.Json
{
public partial class JsonConfigurationProvider : Microsoft.Extensions.Configuration.FileConfigurationProvider
{
public JsonConfigurationProvider(Microsoft.Extensions.Configuration.Json.JsonConfigurationSource source) : base (default(Microsoft.Extensions.Configuration.FileConfigurationSource)) { }
public override System.Collections.Generic.IEnumerable<string> GetChildKeys(System.Collections.Generic.IEnumerable<string> earlierKeys, string? parentPath) { throw null; }
public override string GetDelimiter() { throw null; }
public override void Load(System.IO.Stream stream) { }
}
public partial class JsonConfigurationSource : Microsoft.Extensions.Configuration.FileConfigurationSource
{
public JsonConfigurationSource() { }
public string Separator { get { throw null; } set { } }
public override Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) { throw null; }
}
public partial class JsonStreamConfigurationProvider : Microsoft.Extensions.Configuration.StreamConfigurationProvider
Expand All @@ -36,6 +44,7 @@ public override void Load(System.IO.Stream stream) { }
public partial class JsonStreamConfigurationSource : Microsoft.Extensions.Configuration.StreamConfigurationSource
{
public JsonStreamConfigurationSource() { }
public string Separator { get { throw null; } set { } }
public override Microsoft.Extensions.Configuration.IConfigurationProvider Build(Microsoft.Extensions.Configuration.IConfigurationBuilder builder) { throw null; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,19 @@ public static class JsonConfigurationExtensions
/// <param name="path">Path relative to the base path stored in
/// <see cref="IConfigurationBuilder.Properties"/> of <paramref name="builder"/>.</param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path)
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path) => AddJsonFile(builder, path, ":");

/// <summary>
/// Adds the JSON configuration provider at <paramref name="path"/> to <paramref name="builder"/>.
/// </summary>
/// <param name="builder">The <see cref="IConfigurationBuilder"/> to add to.</param>
/// <param name="path">Path relative to the base path stored in
/// <see cref="IConfigurationBuilder.Properties"/> of <paramref name="builder"/>.</param>
/// <param name="separator"></param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, string separator)
{
return AddJsonFile(builder, provider: null, path: path, optional: false, reloadOnChange: false);
return AddJsonFile(builder, provider: null, path: path, optional: false, reloadOnChange: false, separator);
}

/// <summary>
Expand All @@ -33,7 +43,18 @@ public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder build
/// <see cref="IConfigurationBuilder.Properties"/> of <paramref name="builder"/>.</param>
/// <param name="optional">Whether the file is optional.</param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, bool optional)
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, bool optional) => AddJsonFile(builder, path, optional, ":");

/// <summary>
/// Adds the JSON configuration provider at <paramref name="path"/> to <paramref name="builder"/>.
/// </summary>
/// <param name="builder">The <see cref="IConfigurationBuilder"/> to add to.</param>
/// <param name="path">Path relative to the base path stored in
/// <see cref="IConfigurationBuilder.Properties"/> of <paramref name="builder"/>.</param>
/// <param name="optional">Whether the file is optional.</param>
/// <param name="separator"></param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, bool optional, string separator)
{
return AddJsonFile(builder, provider: null, path: path, optional: optional, reloadOnChange: false);
}
Expand All @@ -47,9 +68,21 @@ public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder build
/// <param name="optional">Whether the file is optional.</param>
/// <param name="reloadOnChange">Whether the configuration should be reloaded if the file changes.</param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange)
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange) => AddJsonFile(builder, path, optional, reloadOnChange, ":");

/// <summary>
/// Adds the JSON configuration provider at <paramref name="path"/> to <paramref name="builder"/>.
/// </summary>
/// <param name="builder">The <see cref="IConfigurationBuilder"/> to add to.</param>
/// <param name="path">Path relative to the base path stored in
/// <see cref="IConfigurationBuilder.Properties"/> of <paramref name="builder"/>.</param>
/// <param name="optional">Whether the file is optional.</param>
/// <param name="reloadOnChange">Whether the configuration should be reloaded if the file changes.</param>
/// <param name="separator"></param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange, string separator)
{
return AddJsonFile(builder, provider: null, path: path, optional: optional, reloadOnChange: reloadOnChange);
return AddJsonFile(builder, provider: null, path: path, optional: optional, reloadOnChange: reloadOnChange, separator);
}

/// <summary>
Expand All @@ -62,7 +95,20 @@ public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder build
/// <param name="optional">Whether the file is optional.</param>
/// <param name="reloadOnChange">Whether the configuration should be reloaded if the file changes.</param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder!!, IFileProvider? provider, string path, bool optional, bool reloadOnChange)
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder!!, IFileProvider? provider, string path, bool optional, bool reloadOnChange) => AddJsonFile(builder, provider, path, optional, reloadOnChange, ":");

/// <summary>
/// Adds a JSON configuration source to <paramref name="builder"/>.
/// </summary>
/// <param name="builder">The <see cref="IConfigurationBuilder"/> to add to.</param>
/// <param name="provider">The <see cref="IFileProvider"/> to use to access the file.</param>
/// <param name="path">Path relative to the base path stored in
/// <see cref="IConfigurationBuilder.Properties"/> of <paramref name="builder"/>.</param>
/// <param name="optional">Whether the file is optional.</param>
/// <param name="reloadOnChange">Whether the configuration should be reloaded if the file changes.</param>
/// <param name="separator"></param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder!!, IFileProvider? provider, string path, bool optional, bool reloadOnChange, string separator = ":")
{
if (string.IsNullOrEmpty(path))
{
Expand All @@ -76,6 +122,7 @@ public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder build
s.Optional = optional;
s.ReloadOnChange = reloadOnChange;
s.ResolveFileProvider();
s.Separator = separator;
});
}

Expand All @@ -94,9 +141,22 @@ public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder build
/// <param name="builder">The <see cref="IConfigurationBuilder"/> to add to.</param>
/// <param name="stream">The <see cref="Stream"/> to read the json configuration data from.</param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonStream(this IConfigurationBuilder builder!!, Stream stream)
public static IConfigurationBuilder AddJsonStream(this IConfigurationBuilder builder!!, Stream stream) => AddJsonStream(builder, stream, ":");

/// <summary>
/// Adds a JSON configuration source to <paramref name="builder"/>.
/// </summary>
/// <param name="builder">The <see cref="IConfigurationBuilder"/> to add to.</param>
/// <param name="stream">The <see cref="Stream"/> to read the json configuration data from.</param>
/// <param name="separator"></param>
/// <returns>The <see cref="IConfigurationBuilder"/>.</returns>
public static IConfigurationBuilder AddJsonStream(this IConfigurationBuilder builder!!, Stream stream, string separator = ":")
{
return builder.Add<JsonStreamConfigurationSource>(s => s.Stream = stream);
return builder.Add<JsonStreamConfigurationSource>(s =>
{
s.Stream = stream;
s.Separator = separator;
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ namespace Microsoft.Extensions.Configuration.Json
{
internal sealed class JsonConfigurationFileParser
{
private JsonConfigurationFileParser() { }
private JsonConfigurationFileParser(string separator = ":")
{
_separator = separator;
}

private readonly Dictionary<string, string?> _data = new Dictionary<string, string?>(StringComparer.OrdinalIgnoreCase);
private readonly Stack<string> _paths = new Stack<string>();
private readonly string _separator;

public static IDictionary<string, string?> Parse(Stream input)
=> new JsonConfigurationFileParser().ParseStream(input);
public static IDictionary<string, string?> Parse(Stream input, string separator = ":")
{
return new JsonConfigurationFileParser(separator).ParseStream(input);
}

private IDictionary<string, string?> ParseStream(Stream input)
{
Expand Down Expand Up @@ -99,7 +105,7 @@ private void VisitValue(JsonElement value)

private void EnterContext(string context) =>
_paths.Push(_paths.Count > 0 ?
_paths.Peek() + ConfigurationPath.KeyDelimiter + context :
_paths.Peek() + _separator + context :
context);

private void ExitContext() => _paths.Pop();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@ namespace Microsoft.Extensions.Configuration.Json
/// </summary>
public class JsonConfigurationProvider : FileConfigurationProvider
{
private readonly string _separator;

public override string GetDelimiter() => _separator;

/// <summary>
/// Initializes a new instance with the specified source.
/// </summary>
/// <param name="source">The source settings.</param>
public JsonConfigurationProvider(JsonConfigurationSource source) : base(source) { }
public JsonConfigurationProvider(JsonConfigurationSource source) : base(source)
{
_separator = source.Separator;
}

/// <summary>
/// Loads the JSON data from a stream.
Expand All @@ -27,12 +34,50 @@ public override void Load(Stream stream)
{
try
{
Data = JsonConfigurationFileParser.Parse(stream);
Data = JsonConfigurationFileParser.Parse(stream, _separator);
}
catch (JsonException e)
{
throw new FormatException(SR.Error_JSONParseError, e);
}
}

public override IEnumerable<string> GetChildKeys(IEnumerable<string> earlierKeys, string? parentPath)
{
var results = new List<string>();

if (parentPath is null)
{
foreach (KeyValuePair<string, string?> kv in Data)
{
results.Add(Segment(kv.Key, 0));
}
}
else
{
foreach (KeyValuePair<string, string?> kv in Data)
{
if (kv.Key.Length > parentPath.Length &&
kv.Key.StartsWith(parentPath, StringComparison.OrdinalIgnoreCase) &&
kv.Key[parentPath.Length] == _separator[0])
{
results.Add(Segment(kv.Key, parentPath.Length + 1));
}
}
}

results.AddRange(earlierKeys);

results.Sort(Microsoft.Extensions.Configuration.ConfigurationKeyComparer.GetInstanceFor(_separator).Compare);

return results;
}

private string Segment(string key, int prefixLength)
{
int indexOf = key.IndexOf(_separator, prefixLength, StringComparison.OrdinalIgnoreCase);
return indexOf < 0 ? key.Substring(prefixLength) : key.Substring(prefixLength, indexOf - prefixLength);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@ public override IConfigurationProvider Build(IConfigurationBuilder builder)
EnsureDefaults(builder);
return new JsonConfigurationProvider(this);
}

public string Separator { get; set; } = ":";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,7 @@ public class JsonStreamConfigurationSource : StreamConfigurationSource
/// <returns>An <see cref="JsonStreamConfigurationProvider"/></returns>
public override IConfigurationProvider Build(IConfigurationBuilder builder)
=> new JsonStreamConfigurationProvider(this);

public string Separator { get; set; } = "`";
}
}
Loading