mirror of
https://github.com/dotnetcore/AgileConfig.git
synced 2026-10-19 21:41:49 +08:00
107 lines
3.3 KiB
C#
107 lines
3.3 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text.Json;
|
|
using System.Linq;
|
|
|
|
namespace AgileConfig.Server.Common
|
|
{
|
|
/// <summary>
|
|
/// 这个类抄的是微软的实现
|
|
/// </summary>
|
|
public 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;
|
|
|
|
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,
|
|
AllowTrailingCommas = true,
|
|
};
|
|
|
|
using (var reader = new StreamReader(input))
|
|
using (JsonDocument doc = JsonDocument.Parse(reader.ReadToEnd(), jsonDocumentOptions))
|
|
{
|
|
if (doc.RootElement.ValueKind != JsonValueKind.Object)
|
|
{
|
|
throw new FormatException("Error_UnsupportedJSONToken");
|
|
}
|
|
VisitElement(doc.RootElement);
|
|
}
|
|
|
|
return _data;
|
|
}
|
|
|
|
private void VisitElement(JsonElement element)
|
|
{
|
|
foreach (JsonProperty property in element.EnumerateObject())
|
|
{
|
|
EnterContext(property.Name);
|
|
VisitValue(property.Value);
|
|
ExitContext();
|
|
}
|
|
}
|
|
|
|
private void VisitValue(JsonElement value)
|
|
{
|
|
switch (value.ValueKind)
|
|
{
|
|
case JsonValueKind.Object:
|
|
VisitElement(value);
|
|
break;
|
|
|
|
case JsonValueKind.Array:
|
|
int index = 0;
|
|
foreach (JsonElement arrayElement in value.EnumerateArray())
|
|
{
|
|
EnterContext(index.ToString());
|
|
VisitValue(arrayElement);
|
|
ExitContext();
|
|
index++;
|
|
}
|
|
break;
|
|
|
|
case JsonValueKind.Number:
|
|
case JsonValueKind.String:
|
|
case JsonValueKind.True:
|
|
case JsonValueKind.False:
|
|
case JsonValueKind.Null:
|
|
string key = _currentPath;
|
|
if (_data.ContainsKey(key))
|
|
{
|
|
throw new FormatException("Error_KeyIsDuplicated");
|
|
}
|
|
_data[key] = value.ToString();
|
|
break;
|
|
|
|
default:
|
|
throw new FormatException("Error_UnsupportedJSONToken");
|
|
}
|
|
}
|
|
|
|
private void EnterContext(string context)
|
|
{
|
|
_context.Push(context);
|
|
_currentPath = ConfigurationPath.Combine(_context.Reverse());
|
|
}
|
|
|
|
private void ExitContext()
|
|
{
|
|
_context.Pop();
|
|
_currentPath = ConfigurationPath.Combine(_context.Reverse());
|
|
}
|
|
}
|
|
}
|