Skip to content
Merged
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 @@ -3,27 +3,24 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.Json;

namespace Microsoft.Extensions.Configuration.Json
{
internal class JsonConfigurationFileParser
internal sealed class JsonConfigurationFileParser
{
private JsonConfigurationFileParser() { }

private readonly IDictionary<string, string> _data = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private readonly Stack<string> _context = new Stack<string>();
private string _currentPath;
private readonly SortedDictionary<string, string> _data = new SortedDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
private readonly Stack<string> _paths = new Stack<string>();

public static IDictionary<string, string> Parse(Stream input)
=> new JsonConfigurationFileParser().ParseStream(input);

private IDictionary<string, string> ParseStream(Stream input)
{
_data.Clear();

var jsonDocumentOptions = new JsonDocumentOptions
{
CommentHandling = JsonCommentHandling.Skip,
Expand Down Expand Up @@ -55,22 +52,26 @@ private void VisitElement(JsonElement element)
ExitContext();
}

if (isEmpty && _currentPath != null)
if (isEmpty && _paths.Count > 0)
{
_data[_currentPath] = null;
_data[_paths.Peek()] = null;
}
}

private void VisitValue(JsonElement value)
{
switch (value.ValueKind) {
Debug.Assert(_paths.Count > 0);

switch (value.ValueKind)
{
case JsonValueKind.Object:
VisitElement(value);
break;

case JsonValueKind.Array:
int index = 0;
foreach (JsonElement arrayElement in value.EnumerateArray()) {
foreach (JsonElement arrayElement in value.EnumerateArray())
{
EnterContext(index.ToString());
VisitValue(arrayElement);
ExitContext();
Expand All @@ -83,7 +84,7 @@ private void VisitValue(JsonElement value)
case JsonValueKind.True:
case JsonValueKind.False:
case JsonValueKind.Null:
string key = _currentPath;
string key = _paths.Peek();
if (_data.ContainsKey(key))
{
throw new FormatException(SR.Format(SR.Error_KeyIsDuplicated, key));
Expand All @@ -96,16 +97,11 @@ private void VisitValue(JsonElement value)
}
}

private void EnterContext(string context)
{
_context.Push(context);
_currentPath = ConfigurationPath.Combine(_context.Reverse());
}
private void EnterContext(string context) =>
_paths.Push(_paths.Count > 0 ?
_paths.Peek() + ConfigurationPath.KeyDelimiter + context :
context);

private void ExitContext()
{
_context.Pop();
_currentPath = ConfigurationPath.Combine(_context.Reverse());
}
private void ExitContext() => _paths.Pop();
}
}