using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Data.SqlTypes; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Net; using System.Numerics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq.JsonPath; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; using WhatGotChanged.Source; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("WhatGotChanged")] [assembly: AssemblyDescription("Auto-generates changelogs by comparing installed mods against previous Thunderstore versions")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("WhatGotChanged")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("d4e5f6a7-b8c9-0123-4567-89abcdef0123")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace WhatGotChanged { [BepInPlugin("IAmOnTheInternetAndItIsScary.WhatGotChanged", "WhatGotChanged", "1.0.0")] public class WhatGotChangedPlugin : BaseUnityPlugin { internal const string ModName = "WhatGotChanged"; internal const string ModGUID = "IAmOnTheInternetAndItIsScary.WhatGotChanged"; internal const string ModVersion = "1.0.0"; public void Awake() { try { ConfigEntry val = ((BaseUnityPlugin)this).Config.Bind("Filters", "TrackTeams", "", "Filter by Thunderstore team/owner names (comma-separated). Tracks ALL mods published by these teams."); ConfigEntry val2 = ((BaseUnityPlugin)this).Config.Bind("Filters", "TrackMods", "", "Filter by specific Thunderstore mod names (comma-separated). Use the exact name as it appears on Thunderstore."); ConfigEntry val3 = ((BaseUnityPlugin)this).Config.Bind("Output", "DetailLevel", ChangelogWriter.DetailLevel.Simple, "Detail level for changelogs.\nsimple — counts per class (e.g. \"3 methods changed, 1 added\")\ndetailed — lists every change by name\nfull — actual C# code diffs"); ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; Scanner.Run(((BaseUnityPlugin)this).Logger, val.Value, val2.Value, val3.Value); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Fatal error: " + ex.Message)); ((BaseUnityPlugin)this).Logger.LogError((object)ex.StackTrace); } } } } namespace WhatGotChanged.Source { public static class Scanner { public static void Run(ManualLogSource log, string trackTeams, string trackMods, ChangelogWriter.DetailLevel detailLevel) { log.LogInfo((object)"=== WhatGotChanged? ==="); if (string.IsNullOrEmpty(trackTeams) && string.IsNullOrEmpty(trackMods)) { log.LogInfo((object)"No mods configured — edit config to add TrackTeams or TrackMods"); return; } List list = ThunderstoreApi.FetchPackageList(log); if (list == null || list.Count == 0) { log.LogWarning((object)"Could not fetch Thunderstore data — are you offline?"); return; } Dictionary dictionary = ModDiscovery.GatherCandidates(log, trackTeams, trackMods, list); if (dictionary.Count == 0) { log.LogInfo((object)"No installed mods matched configured filters"); return; } Dictionary dictionary2 = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (ThunderstoreApi.PackageInfo item in list) { string key = item.Owner + "/" + item.Name; if (!dictionary2.ContainsKey(key)) { dictionary2[key] = item; } } log.LogInfo((object)$"Scanning {dictionary.Count} package(s)..."); string text = Path.Combine(Paths.ConfigPath, "WhatGotChanged"); Directory.CreateDirectory(text); int num = 0; foreach (KeyValuePair item2 in dictionary) { string key2 = item2.Key; string value = item2.Value; ThunderstoreApi.PackageInfo packageInfo = dictionary2[key2]; if (packageInfo.Versions.Count < 2) { log.LogInfo((object)(" " + packageInfo.Name + " — only 1 version, nothing to compare")); continue; } ThunderstoreApi.VersionInfo versionInfo = packageInfo.Versions[0]; ThunderstoreApi.VersionInfo versionInfo2 = packageInfo.Versions[1]; string text2 = Path.Combine(text, packageInfo.Name + "-" + versionInfo.VersionNumber + ".md"); if (File.Exists(text2)) { log.LogInfo((object)(" " + packageInfo.Name + " v" + versionInfo.VersionNumber + " — changelog already exists, skipping")); continue; } bool flag = value != versionInfo.VersionNumber; if (flag) { log.LogInfo((object)(" " + packageInfo.Name + ": UPDATE AVAILABLE v" + value + " -> v" + versionInfo.VersionNumber)); } log.LogInfo((object)(" " + packageInfo.Name + ": comparing v" + versionInfo2.VersionNumber + " -> v" + versionInfo.VersionNumber)); string text3 = ThunderstoreApi.FetchDecompiledSource(packageInfo.Owner, packageInfo.Name, versionInfo2.VersionNumber, log); string text4 = ThunderstoreApi.FetchDecompiledSource(packageInfo.Owner, packageInfo.Name, versionInfo.VersionNumber, log); if (text3 == null && text4 == null) { log.LogInfo((object)" Decompiled source not available for either version, skipping"); continue; } if (text3 == null) { log.LogInfo((object)(" Decompiled source not available for v" + versionInfo2.VersionNumber + ", skipping")); continue; } if (text4 == null) { log.LogInfo((object)(" Decompiled source not available for v" + versionInfo.VersionNumber + ", skipping")); continue; } SourceDiffer.DiffResult diffResult = SourceDiffer.Diff(text3, text4, log); if (diffResult.Changes.Count > 0) { log.LogInfo((object)$" {diffResult.Changes.Count} change(s) detected"); } else { log.LogInfo((object)" No code changes — metadata/asset update only"); } ChangelogWriter.WriteChangelog(text2, packageInfo.Name, versionInfo2.VersionNumber, versionInfo.VersionNumber, value, flag, diffResult, detailLevel); num++; } if (num > 0) { log.LogInfo((object)"Changelogs: BepInEx/config/WhatGotChanged/"); } log.LogInfo((object)"=== Scan Complete ==="); } } public static class ModDiscovery { private class InstalledPlugin { public string GUID; public string Name; public string Version; } public static Dictionary GatherCandidates(ManualLogSource log, string trackTeams, string trackMods, List allPackages) { HashSet hashSet = ParseList(trackTeams); HashSet hashSet2 = ParseList(trackMods); Dictionary plugins = BuildInstalledPluginMap(); Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (ThunderstoreApi.PackageInfo allPackage in allPackages) { if (hashSet.Contains(allPackage.Owner) || hashSet2.Contains(allPackage.Name)) { dictionary[allPackage.Owner + "/" + allPackage.Name] = allPackage; } } log.LogInfo((object)$"Config matched {dictionary.Count} package(s) on Thunderstore"); Dictionary dictionary2 = new Dictionary(StringComparer.OrdinalIgnoreCase); int num = 0; int num2 = 0; int num3 = 0; foreach (KeyValuePair item in dictionary) { string key = item.Key; ThunderstoreApi.PackageInfo value = item.Value; string text = FindDirect(value.Owner, value.Name, plugins); if (text != null) { dictionary2[key] = text; num++; log.LogInfo((object)(" " + key + " v" + text + " — found via direct match")); continue; } text = FindViaCfgFiles(value.Name); if (text != null) { dictionary2[key] = text; num2++; log.LogInfo((object)(" " + key + " v" + text + " — found via cfg scan")); continue; } text = FindViaChainloader(value.Owner, value.Name, plugins); if (text != null) { dictionary2[key] = text; num3++; log.LogInfo((object)(" " + key + " v" + text + " — found via chainloader scan")); } else { log.LogInfo((object)(" " + key + " — not installed, skipping")); } } log.LogInfo((object)$"Total installed: {num} direct, {num2} from cfg scan, {num3} from chainloader"); return dictionary2; } private static Dictionary BuildInstalledPluginMap() { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); if (Chainloader.PluginInfos == null) { return dictionary; } foreach (KeyValuePair pluginInfo in Chainloader.PluginInfos) { BepInPlugin metadata = pluginInfo.Value.Metadata; dictionary[metadata.GUID] = new InstalledPlugin { GUID = metadata.GUID, Name = metadata.Name, Version = metadata.Version.ToString() }; } return dictionary; } private static string FindDirect(string owner, string mod, Dictionary plugins) { string[] array = new string[2] { owner + "." + mod, "com." + owner + "." + mod }; string[] array2 = array; foreach (string key in array2) { if (plugins.TryGetValue(key, out var value)) { return value.Version; } } foreach (InstalledPlugin value2 in plugins.Values) { if (!value2.Name.Equals(mod, StringComparison.OrdinalIgnoreCase) || value2.GUID.IndexOf(owner, StringComparison.OrdinalIgnoreCase) < 0) { continue; } return value2.Version; } return null; } private static string FindViaCfgFiles(string mod) { string configPath = Paths.ConfigPath; if (!Directory.Exists(configPath)) { return null; } string value = mod.ToLowerInvariant(); string[] files = Directory.GetFiles(configPath, "*.cfg"); foreach (string path in files) { string text = Path.GetFileNameWithoutExtension(path).ToLowerInvariant(); if (text.Contains(value)) { return "unknown"; } } return null; } private static string FindViaChainloader(string owner, string mod, Dictionary plugins) { if (plugins.Count == 0) { return null; } string text = mod.ToLowerInvariant(); string value = owner.ToLowerInvariant(); InstalledPlugin installedPlugin = null; foreach (InstalledPlugin value2 in plugins.Values) { string text2 = value2.GUID.ToLowerInvariant(); string text3 = value2.Name.ToLowerInvariant(); if (text2.Contains(text) || text3 == text) { if (text2.Contains(value)) { return value2.Version; } if (installedPlugin == null) { installedPlugin = value2; } } } return installedPlugin?.Version; } private static HashSet ParseList(string csv) { return new HashSet(from s in csv.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim(), StringComparer.OrdinalIgnoreCase); } } public static class ThunderstoreApi { public class PackageInfo { [JsonProperty("name")] public string Name { get; set; } = ""; [JsonProperty("owner")] public string Owner { get; set; } = ""; [JsonProperty("versions")] public List Versions { get; set; } = new List(); } public class VersionInfo { [JsonProperty("version_number")] public string VersionNumber { get; set; } = ""; } public class DecompilationResponse { [JsonProperty("decompilations")] public List Decompilations { get; set; } = new List(); } public class DecompilationEntry { [JsonProperty("url")] public string Url { get; set; } = ""; } private const string PackageListUrl = "https://thunderstore.io/c/valheim/api/v1/package/"; private const string DecompilationUrl = "https://thunderstore.io/api/cyberstorm/package/{0}/{1}/v/{2}/source/"; private const string UserAgent = "WhatGotChanged/1.0"; private const int Timeout = 30000; public static List FetchPackageList(ManualLogSource log) { try { log.LogInfo((object)"Fetching Thunderstore package list..."); HttpWebRequest httpWebRequest = CreateRequest("https://thunderstore.io/c/valheim/api/v1/package/"); using HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse(); using StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream()); return JsonConvert.DeserializeObject>(streamReader.ReadToEnd()); } catch (Exception ex) { log.LogWarning((object)("Thunderstore fetch failed: " + ex.Message)); return null; } } public static string FetchDecompiledSource(string owner, string packageName, string version, ManualLogSource log) { try { HttpWebRequest httpWebRequest = CreateRequest($"https://thunderstore.io/api/cyberstorm/package/{owner}/{packageName}/v/{version}/source/"); DecompilationResponse decompilationResponse; using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse()) { using StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream()); decompilationResponse = JsonConvert.DeserializeObject(streamReader.ReadToEnd()); } if (decompilationResponse?.Decompilations == null || decompilationResponse.Decompilations.Count == 0) { return null; } string url = decompilationResponse.Decompilations[0].Url; if (string.IsNullOrEmpty(url)) { return null; } HttpWebRequest httpWebRequest2 = CreateRequest(url); using HttpWebResponse httpWebResponse2 = (HttpWebResponse)httpWebRequest2.GetResponse(); using StreamReader streamReader2 = new StreamReader(httpWebResponse2.GetResponseStream()); return streamReader2.ReadToEnd(); } catch (Exception ex) { log.LogWarning((object)(" Fetch failed for " + owner + "/" + packageName + " v" + version + ": " + ex.Message)); return null; } } private static HttpWebRequest CreateRequest(string url) { HttpWebRequest httpWebRequest = WebRequest.CreateHttp(url); httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; httpWebRequest.Timeout = 30000; httpWebRequest.UserAgent = "WhatGotChanged/1.0"; return httpWebRequest; } } public static class SourceDiffer { public enum ChangeKind { Added, Removed, Modified } public enum ChangeType { Type, Method, Field, Property } public class Change { public ChangeKind Kind; public ChangeType Type; public string ClassName; public string MemberName; public string NewBody; public string OldBody; public Change(ChangeKind kind, ChangeType type, string className, string memberName, string newBody, string oldBody = "") { Kind = kind; Type = type; ClassName = className; MemberName = memberName; NewBody = newBody; OldBody = oldBody; } } public class DiffResult { public List Changes = new List(); } private class ParsedClass { public Dictionary Methods = new Dictionary(StringComparer.OrdinalIgnoreCase); public List Fields = new List(); public List Properties = new List(); } private static readonly string[] AccessModifiers = new string[13] { "public", "private", "protected", "internal", "static", "abstract", "sealed", "partial", "readonly", "new", "override", "virtual", "unsafe" }; private static readonly string[] TypeKeywords = new string[4] { "class", "struct", "interface", "enum" }; private static readonly HashSet ReservedWords = new HashSet { "class", "struct", "interface", "enum", "namespace", "return", "using", "get", "set" }; public static DiffResult Diff(string oldSource, string newSource, ManualLogSource log = null) { DiffResult diffResult = new DiffResult(); Dictionary dictionary = ParseSource(oldSource); Dictionary dictionary2 = ParseSource(newSource); if (log != null) { int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; foreach (ParsedClass value2 in dictionary.Values) { num += value2.Methods.Count; num3 += value2.Fields.Count + value2.Properties.Count; } foreach (ParsedClass value3 in dictionary2.Values) { num2 += value3.Methods.Count; num4 += value3.Fields.Count + value3.Properties.Count; } log.LogInfo((object)$" Parsed: {dictionary.Count}/{dictionary2.Count} classes, {num}/{num2} methods, {num3}/{num4} fields+props"); } foreach (KeyValuePair item in dictionary2) { if (!dictionary.ContainsKey(item.Key)) { diffResult.Changes.Add(new Change(ChangeKind.Added, ChangeType.Type, item.Key, "", "")); } } foreach (KeyValuePair item2 in dictionary) { if (!dictionary2.ContainsKey(item2.Key)) { diffResult.Changes.Add(new Change(ChangeKind.Removed, ChangeType.Type, item2.Key, "", "")); } } foreach (KeyValuePair item3 in dictionary2) { if (dictionary.TryGetValue(item3.Key, out var value)) { DiffMembers(item3.Key, value, item3.Value, diffResult); } } return diffResult; } private static void DiffMembers(string className, ParsedClass oldClass, ParsedClass newClass, DiffResult result) { string className2 = (className.Contains(".") ? className.Substring(className.LastIndexOf('.') + 1) : className); foreach (KeyValuePair method in newClass.Methods) { if (!oldClass.Methods.ContainsKey(method.Key)) { result.Changes.Add(new Change(ChangeKind.Added, ChangeType.Method, className2, method.Key, method.Value)); } } foreach (KeyValuePair method2 in oldClass.Methods) { if (!newClass.Methods.ContainsKey(method2.Key)) { result.Changes.Add(new Change(ChangeKind.Removed, ChangeType.Method, className2, method2.Key, method2.Value)); } } foreach (KeyValuePair method3 in newClass.Methods) { if (oldClass.Methods.TryGetValue(method3.Key, out var value) && value != method3.Value) { result.Changes.Add(new Change(ChangeKind.Modified, ChangeType.Method, className2, method3.Key, method3.Value, value)); } } DiffStringSet(oldClass.Fields, newClass.Fields, ChangeType.Field, className2, result); DiffStringSet(oldClass.Properties, newClass.Properties, ChangeType.Property, className2, result); } private static void DiffStringSet(List oldItems, List newItems, ChangeType type, string className, DiffResult result) { HashSet hashSet = new HashSet(oldItems, StringComparer.OrdinalIgnoreCase); HashSet hashSet2 = new HashSet(newItems, StringComparer.OrdinalIgnoreCase); foreach (string item in hashSet2.Except(hashSet)) { result.Changes.Add(new Change(ChangeKind.Added, type, className, item, "")); } foreach (string item2 in hashSet.Except(hashSet2)) { result.Changes.Add(new Change(ChangeKind.Removed, type, className, item2, "")); } } private static Dictionary ParseSource(string source) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); string[] array = source.Split(new char[2] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); string text = ""; string text2 = ""; ParsedClass parsedClass = null; int num = 0; int num2 = -1; int num3 = -1; bool flag = false; List list = new List(); string key = ""; foreach (string text3 in array) { string text4 = text3.Trim(); if (text4.StartsWith("namespace ")) { text = text4.Substring("namespace ".Length).TrimEnd('{', ' ', '\t'); } int num4 = text4.Count((char c) => c == '{'); int num5 = text4.Count((char c) => c == '}'); int num6 = num + num4 - num5; if (flag && num4 > 0) { num2 = num + 1; flag = false; } if ((parsedClass == null || num < num2) && IsTypeDeclaration(text4, out var name)) { string text5 = (string.IsNullOrEmpty(text) ? name : (text + "." + name)); if (parsedClass != null && num >= num2) { text5 = text2 + "." + name; } text2 = text5; parsedClass = new ParsedClass(); if (num4 > 0) { num2 = num + 1; } else { flag = true; } if (!dictionary.ContainsKey(text5)) { dictionary[text5] = parsedClass; } } if (parsedClass != null && num >= num2 && num2 > 0 && !flag) { string signature; string signature2; string signature3; if (text4 == "{" || text4 == "}") { if (num3 >= 0) { list.Add(text3); if (num6 <= num3) { parsedClass.Methods[key] = string.Join("\n", list); num3 = -1; list.Clear(); } } } else if (num3 >= 0) { list.Add(text3); if (num6 <= num3) { parsedClass.Methods[key] = string.Join("\n", list); num3 = -1; list.Clear(); } } else if (IsMethodDeclaration(text4, out signature)) { key = signature; list.Clear(); list.Add(text3); if (text4.Contains("=>") || (num4 > 0 && num5 > 0 && num4 == num5)) { parsedClass.Methods[signature] = text3; list.Clear(); } else { num3 = num; } } else if (IsFieldDeclaration(text4, out signature2)) { parsedClass.Fields.Add(signature2); } else if (IsPropertyDeclaration(text4, out signature3)) { parsedClass.Properties.Add(signature3); } } num = num6; if (parsedClass != null && num < num2) { parsedClass = null; num2 = -1; } } return dictionary; } private static bool IsTypeDeclaration(string line, out string name) { name = ""; string input = line; string[] accessModifiers = AccessModifiers; foreach (string text in accessModifiers) { input = Regex.Replace(input, "\\b" + text + "\\b", "").Trim(); } string[] typeKeywords = TypeKeywords; foreach (string text2 in typeKeywords) { Match match = Regex.Match(input, "\\b" + text2 + "\\s+(\\w+)"); if (match.Success) { name = match.Groups[1].Value; return true; } } return false; } private static bool IsMethodDeclaration(string line, out string signature) { signature = ""; if (line.StartsWith("[") || line.StartsWith("//") || line.StartsWith("/*") || line.Contains(" event ")) { return false; } Match match = Regex.Match(line, "(?:(?:public|private|protected|internal|static|virtual|override|abstract|sealed|async|new|extern|unsafe)\\s+)*(\\w[\\w<>\\[\\],\\s\\?]*)\\s+(\\w+)\\s*\\(([^)]*)\\)"); if (match.Success) { string item = match.Groups[1].Value.Trim(); if (ReservedWords.Contains(item)) { return false; } signature = match.Groups[2].Value.Trim() + "(" + SimplifyParams(match.Groups[3].Value.Trim()) + ")"; return true; } match = Regex.Match(line, "(?:(?:public|private|protected|internal|static)\\s+)+(\\w+)\\s*\\(([^)]*)\\)\\s*(?::|{)"); if (match.Success) { signature = match.Groups[1].Value.Trim() + "(" + SimplifyParams(match.Groups[2].Value.Trim()) + ")"; return true; } return false; } private static string SimplifyParams(string parameters) { if (string.IsNullOrWhiteSpace(parameters)) { return ""; } return string.Join(", ", from p in parameters.Split(new char[1] { ',' }) select p.Trim().Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries) into t where t.Length >= 1 select t[0]); } private static bool IsFieldDeclaration(string line, out string signature) { signature = ""; if (line.Contains("(") || line.Contains("=>") || line.StartsWith("[") || line.StartsWith("//") || line.Contains(" event ")) { return false; } Match match = Regex.Match(line, "(?:(?:public|private|protected|internal|static|readonly|const|volatile|new|unsafe)\\s+)*(\\w[\\w<>\\[\\],\\?\\s]*)\\s+(\\w+)\\s*[;=]"); if (!match.Success) { return false; } string text = match.Groups[1].Value.Trim(); if (ReservedWords.Contains(text)) { return false; } signature = text + " " + match.Groups[2].Value.Trim(); return true; } private static bool IsPropertyDeclaration(string line, out string signature) { signature = ""; Match match = Regex.Match(line, "(?:(?:public|private|protected|internal|static|virtual|override|abstract|new|unsafe)\\s+)*(\\w[\\w<>\\[\\],\\?\\s]*)\\s+(\\w+)\\s*\\{"); if (!match.Success || (!line.Contains("get") && !line.Contains("set"))) { return false; } string text = match.Groups[1].Value.Trim(); if (ReservedWords.Contains(text)) { return false; } signature = text + " " + match.Groups[2].Value.Trim(); return true; } } public static class ChangelogWriter { public enum DetailLevel { Simple, Detailed, Full } public static void WriteChangelog(string outputPath, string modName, string oldVersion, string newVersion, string installedVersion, bool hasUpdate, SourceDiffer.DiffResult diff, DetailLevel level) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("# " + modName); stringBuilder.AppendLine("`v" + oldVersion + "` → `v" + newVersion + "`"); stringBuilder.AppendLine(); if (hasUpdate && !string.IsNullOrEmpty(installedVersion)) { stringBuilder.AppendLine("> ⚠ **Update available:** you have `v" + installedVersion + "`, latest is `v" + newVersion + "`"); stringBuilder.AppendLine(); } stringBuilder.AppendLine($"*Generated {DateTime.Now:yyyy-MM-dd HH:mm}*"); stringBuilder.AppendLine(); stringBuilder.AppendLine("---"); stringBuilder.AppendLine(); if (diff.Changes.Count == 0) { stringBuilder.AppendLine("No code changes — metadata/asset update only."); stringBuilder.AppendLine(); } else { switch (level) { case DetailLevel.Simple: WriteSimple(stringBuilder, diff); break; case DetailLevel.Detailed: WriteDetailed(stringBuilder, diff); break; case DetailLevel.Full: WriteFull(stringBuilder, diff); break; } } File.WriteAllText(outputPath, stringBuilder.ToString()); } private static IEnumerable> GroupByClass(SourceDiffer.DiffResult diff) { return from c in diff.Changes group c by c.ClassName into g orderby g.Key select g; } private static void WriteSimple(StringBuilder sb, SourceDiffer.DiffResult diff) { foreach (IGrouping item in GroupByClass(diff)) { IGrouping group = item; SourceDiffer.Change change = group.FirstOrDefault((SourceDiffer.Change c) => c.Type == SourceDiffer.ChangeType.Type); if (change != null) { sb.AppendLine("- **" + group.Key + "**: " + ((change.Kind == SourceDiffer.ChangeKind.Added) ? "new" : "removed") + " type"); continue; } List parts = new List(); Count(SourceDiffer.ChangeType.Method, SourceDiffer.ChangeKind.Added, "method(s) added"); Count(SourceDiffer.ChangeType.Method, SourceDiffer.ChangeKind.Modified, "method(s) changed"); Count(SourceDiffer.ChangeType.Method, SourceDiffer.ChangeKind.Removed, "method(s) removed"); Count(SourceDiffer.ChangeType.Field, SourceDiffer.ChangeKind.Added, "field(s) added"); Count(SourceDiffer.ChangeType.Field, SourceDiffer.ChangeKind.Removed, "field(s) removed"); Count(SourceDiffer.ChangeType.Property, SourceDiffer.ChangeKind.Added, "property(s) added"); Count(SourceDiffer.ChangeType.Property, SourceDiffer.ChangeKind.Removed, "property(s) removed"); if (parts.Count > 0) { sb.AppendLine("- **" + group.Key + "**: " + string.Join(", ", parts)); } void Count(SourceDiffer.ChangeType type, SourceDiffer.ChangeKind kind, string label) { int num = group.Count((SourceDiffer.Change c) => c.Type == type && c.Kind == kind); if (num > 0) { parts.Add($"{num} {label}"); } } } sb.AppendLine(); } private static void WriteDetailed(StringBuilder sb, SourceDiffer.DiffResult diff) { foreach (IGrouping item in GroupByClass(diff)) { sb.AppendLine("### " + item.Key); sb.AppendLine(); foreach (SourceDiffer.Change item2 in item.Where((SourceDiffer.Change c) => c.Kind == SourceDiffer.ChangeKind.Added)) { sb.AppendLine("- + `" + FormatMember(item2) + "`"); } foreach (SourceDiffer.Change item3 in item.Where((SourceDiffer.Change c) => c.Kind == SourceDiffer.ChangeKind.Removed)) { sb.AppendLine("- - `" + FormatMember(item3) + "`"); } foreach (SourceDiffer.Change item4 in item.Where((SourceDiffer.Change c) => c.Kind == SourceDiffer.ChangeKind.Modified)) { sb.AppendLine("- ~ `" + FormatMember(item4) + "`"); } sb.AppendLine(); } } private static void WriteFull(StringBuilder sb, SourceDiffer.DiffResult diff) { foreach (IGrouping item in GroupByClass(diff)) { sb.AppendLine("### " + item.Key); sb.AppendLine(); foreach (SourceDiffer.Change item2 in item) { sb.AppendLine("**" + KindSymbol(item2.Kind) + " " + FormatMember(item2) + "**"); if (item2.Type == SourceDiffer.ChangeType.Method) { if (item2.Kind == SourceDiffer.ChangeKind.Modified) { WriteLineDiff(sb, item2.OldBody, item2.NewBody); } else { string text = ((item2.Kind == SourceDiffer.ChangeKind.Added) ? item2.NewBody : item2.OldBody); if (!string.IsNullOrEmpty(text)) { string text2 = ((item2.Kind == SourceDiffer.ChangeKind.Added) ? "+" : "-"); sb.AppendLine("```csharp"); string[] array = text.Split(new char[1] { '\n' }); foreach (string text3 in array) { sb.AppendLine(text2 + " " + text3); } sb.AppendLine("```"); } } } sb.AppendLine(); } } } private static void WriteLineDiff(StringBuilder sb, string oldBody, string newBody) { string[] array = oldBody.Split(new char[1] { '\n' }); string[] array2 = newBody.Split(new char[1] { '\n' }); int num = array.Length; int num2 = array2.Length; int[,] array3 = new int[num + 1, num2 + 1]; for (int num3 = num - 1; num3 >= 0; num3--) { for (int num4 = num2 - 1; num4 >= 0; num4--) { array3[num3, num4] = ((array[num3].Trim() == array2[num4].Trim()) ? (array3[num3 + 1, num4 + 1] + 1) : Math.Max(array3[num3 + 1, num4], array3[num3, num4 + 1])); } } sb.AppendLine("```diff"); int num5 = 0; int num6 = 0; while (num5 < num || num6 < num2) { if (num5 < num && num6 < num2 && array[num5].Trim() == array2[num6].Trim()) { sb.AppendLine(" " + array2[num6]); num5++; num6++; } else if (num6 < num2 && (num5 >= num || array3[num5, num6 + 1] >= array3[num5 + 1, num6])) { sb.AppendLine("+ " + array2[num6]); num6++; } else if (num5 < num) { sb.AppendLine("- " + array[num5]); num5++; } } sb.AppendLine("```"); } private static string KindSymbol(SourceDiffer.ChangeKind kind) { return kind switch { SourceDiffer.ChangeKind.Added => "+", SourceDiffer.ChangeKind.Removed => "-", _ => "~", }; } private static string FormatMember(SourceDiffer.Change change) { return change.Type.ToString().ToLower() + ": " + change.MemberName; } } } [CompilerGenerated] internal sealed class { [StructLayout(LayoutKind.Explicit, Pack = 1, Size = 6)] internal struct __StaticArrayInitTypeSize=6 { } internal static readonly __StaticArrayInitTypeSize=6 515E2C3AE1FA25341D4979E6610F37196C07BB55D83828D69D8FCD2331395EE0/* Not supported: data(7B 00 20 00 09 00) */; } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } } namespace Newtonsoft.Json { internal enum ConstructorHandling { Default, AllowNonPublicDefaultConstructor } internal enum DateFormatHandling { IsoDateFormat, MicrosoftDateFormat } internal enum DateParseHandling { None, DateTime, DateTimeOffset } internal enum DateTimeZoneHandling { Local, Utc, Unspecified, RoundtripKind } internal class DefaultJsonNameTable : JsonNameTable { private class Entry { internal readonly string Value; internal readonly int HashCode; internal Entry Next; internal Entry(string value, int hashCode, Entry next) { Value = value; HashCode = hashCode; Next = next; } } private static readonly int HashCodeRandomizer; private int _count; private Entry[] _entries; private int _mask = 31; static DefaultJsonNameTable() { HashCodeRandomizer = Environment.TickCount; } public DefaultJsonNameTable() { _entries = new Entry[_mask + 1]; } public override string? Get(char[] key, int start, int length) { if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; num += (num << 7) ^ key[start]; int num2 = start + length; for (int i = start + 1; i < num2; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; int num3 = Volatile.Read(ref _mask); int num4 = num & num3; for (Entry entry = _entries[num4]; entry != null; entry = entry.Next) { if (entry.HashCode == num && TextEquals(entry.Value, key, start, length)) { return entry.Value; } } return null; } public string Add(string key) { if (key == null) { throw new ArgumentNullException("key"); } int length = key.Length; if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; for (int i = 0; i < key.Length; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next) { if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal)) { return entry.Value; } } return AddEntry(key, num); } private string AddEntry(string str, int hashCode) { int num = hashCode & _mask; Entry entry = new Entry(str, hashCode, _entries[num]); _entries[num] = entry; if (_count++ == _mask) { Grow(); } return entry.Value; } private void Grow() { Entry[] entries = _entries; int num = _mask * 2 + 1; Entry[] array = new Entry[num + 1]; for (int i = 0; i < entries.Length; i++) { Entry entry = entries[i]; while (entry != null) { int num2 = entry.HashCode & num; Entry next = entry.Next; entry.Next = array[num2]; array[num2] = entry; entry = next; } } _entries = array; Volatile.Write(ref _mask, num); } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) { if (str1.Length != str2Length) { return false; } for (int i = 0; i < str1.Length; i++) { if (str1[i] != str2[str2Start + i]) { return false; } } return true; } } [Flags] internal enum DefaultValueHandling { Include = 0, Ignore = 1, Populate = 2, IgnoreAndPopulate = 3 } internal enum FloatFormatHandling { String, Symbol, DefaultValue } internal enum FloatParseHandling { Double, Decimal } internal enum Formatting { None, Indented } internal interface IArrayPool { T[] Rent(int minimumLength); void Return(T[]? array); } internal interface IJsonLineInfo { int LineNumber { get; } int LinePosition { get; } bool HasLineInfo(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] internal sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; public bool AllowNullItems { get { return _allowNullItems; } set { _allowNullItems = value; } } public JsonArrayAttribute() { } public JsonArrayAttribute(bool allowNullItems) { _allowNullItems = allowNullItems; } public JsonArrayAttribute(string id) : base(id) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] internal sealed class JsonConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] internal abstract class JsonContainerAttribute : Attribute { internal bool? _isReference; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; private Type? _namingStrategyType; private object[]? _namingStrategyParameters; public string? Id { get; set; } public string? Title { get; set; } public string? Description { get; set; } public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get { return _namingStrategyType; } set { _namingStrategyType = value; NamingStrategyInstance = null; } } public object[]? NamingStrategyParameters { get { return _namingStrategyParameters; } set { _namingStrategyParameters = value; NamingStrategyInstance = null; } } internal NamingStrategy? NamingStrategyInstance { get; set; } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } protected JsonContainerAttribute() { } protected JsonContainerAttribute(string id) { Id = id; } } internal static class JsonConvert { public static readonly string True = "true"; public static readonly string False = "false"; public static readonly string Null = "null"; public static readonly string Undefined = "undefined"; public static readonly string PositiveInfinity = "Infinity"; public static readonly string NegativeInfinity = "-Infinity"; public static readonly string NaN = "NaN"; public static Func? DefaultSettings { get; set; } public static string ToString(DateTime value) { return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); } public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(DateTimeOffset value) { return ToString(value, DateFormatHandling.IsoDateFormat); } public static string ToString(DateTimeOffset value, DateFormatHandling format) { using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(bool value) { if (!value) { return False; } return True; } public static string ToString(char value) { return ToString(char.ToString(value)); } public static string ToString(Enum value) { return value.ToString("D"); } public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } private static string ToStringInternal(BigInteger value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value))) { return text; } if (floatFormatHandling == FloatFormatHandling.DefaultValue) { if (nullable) { return Null; } return "0.0"; } return quoteChar + text + quoteChar; } public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (StringUtils.IndexOf(text, '.') != -1) { return text; } return text + ".0"; } public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } public static string ToString(Guid value) { return ToString(value, '"'); } internal static string ToString(Guid value, char quoteChar) { string text = value.ToString("D", CultureInfo.InvariantCulture); string text2 = quoteChar.ToString(CultureInfo.InvariantCulture); return text2 + text + text2; } public static string ToString(TimeSpan value) { return ToString(value, '"'); } internal static string ToString(TimeSpan value, char quoteChar) { return ToString(value.ToString(), quoteChar); } public static string ToString(Uri? value) { if (value == null) { return Null; } return ToString(value, '"'); } internal static string ToString(Uri value, char quoteChar) { return ToString(value.OriginalString, quoteChar); } public static string ToString(string? value) { return ToString(value, '"'); } public static string ToString(string? value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } public static string ToString(string? value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter"); } return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling); } public static string ToString(object? value) { if (value == null) { return Null; } return ConvertUtils.GetTypeCode(value.GetType()) switch { PrimitiveTypeCode.String => ToString((string)value), PrimitiveTypeCode.Char => ToString((char)value), PrimitiveTypeCode.Boolean => ToString((bool)value), PrimitiveTypeCode.SByte => ToString((sbyte)value), PrimitiveTypeCode.Int16 => ToString((short)value), PrimitiveTypeCode.UInt16 => ToString((ushort)value), PrimitiveTypeCode.Int32 => ToString((int)value), PrimitiveTypeCode.Byte => ToString((byte)value), PrimitiveTypeCode.UInt32 => ToString((uint)value), PrimitiveTypeCode.Int64 => ToString((long)value), PrimitiveTypeCode.UInt64 => ToString((ulong)value), PrimitiveTypeCode.Single => ToString((float)value), PrimitiveTypeCode.Double => ToString((double)value), PrimitiveTypeCode.DateTime => ToString((DateTime)value), PrimitiveTypeCode.Decimal => ToString((decimal)value), PrimitiveTypeCode.DBNull => Null, PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), PrimitiveTypeCode.Guid => ToString((Guid)value), PrimitiveTypeCode.Uri => ToString((Uri)value), PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), _ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), }; } [DebuggerStepThrough] public static string SerializeObject(object? value) { return SerializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static string SerializeObject(object? value, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, JsonSerializerSettings? settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] public static string SerializeObject(object? value, Formatting formatting, JsonSerializerSettings? settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object? value, Type? type, Formatting formatting, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; return SerializeObjectInternal(value, type, jsonSerializer); } private static string SerializeObjectInternal(object? value, Type? type, JsonSerializer jsonSerializer) { StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } [DebuggerStepThrough] public static object? DeserializeObject(string value) { return DeserializeObject(value, (Type?)null, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static object? DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeObject(string value) { return JsonConvert.DeserializeObject(value, (JsonSerializerSettings?)null); } [DebuggerStepThrough] public static T? DeserializeAnonymousType(string value, T anonymousTypeObject) { return DeserializeObject(value); } [DebuggerStepThrough] public static T? DeserializeAnonymousType(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject(value, settings); } [DebuggerStepThrough] public static T? DeserializeObject(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] public static T? DeserializeObject(string value, JsonSerializerSettings? settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] public static object? DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return DeserializeObject(value, type, settings); } public static object? DeserializeObject(string value, Type? type, JsonSerializerSettings? settings) { ValidationUtils.ArgumentNotNull(value, "value"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); if (!jsonSerializer.IsCheckAdditionalContentSet()) { jsonSerializer.CheckAdditionalContent = true; } using JsonTextReader reader = new JsonTextReader(new StringReader(value)); return jsonSerializer.Deserialize(reader, type); } [DebuggerStepThrough] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } public static void PopulateObject(string value, object target, JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); using JsonReader jsonReader = new JsonTextReader(new StringReader(value)); jsonSerializer.Populate(jsonReader, target); if (settings == null || !settings.CheckAdditionalContent) { return; } while (jsonReader.Read()) { if (jsonReader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); } } } public static string SerializeXmlNode(XmlNode? node) { return SerializeXmlNode(node, Formatting.None); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); return SerializeObject(node, formatting, xmlNodeConverter); } public static string SerializeXmlNode(XmlNode? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XmlDocument? DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XmlDocument? DeserializeXmlNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter); } public static string SerializeXNode(XObject? node) { return SerializeXNode(node, Formatting.None); } public static string SerializeXNode(XObject? node, Formatting formatting) { return SerializeXNode(node, formatting, omitRootObject: false); } public static string SerializeXNode(XObject? node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XDocument? DeserializeXNode(string value) { return DeserializeXNode(value, null); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XDocument? DeserializeXNode(string value, string? deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter); } } internal abstract class JsonConverter { public virtual bool CanRead => true; public virtual bool CanWrite => true; public abstract void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer); public abstract object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer); public abstract bool CanConvert(Type objectType); } internal abstract class JsonConverter : JsonConverter { public sealed override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } WriteJson(writer, (T)value, serializer); } public abstract void WriteJson(JsonWriter writer, T? value, JsonSerializer serializer); public sealed override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = existingValue == null; if (!flag && !(existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer); } public abstract T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer); public sealed override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class JsonConverterAttribute : Attribute { private readonly Type _converterType; public Type ConverterType => _converterType; public object[]? ConverterParameters { get; } public JsonConverterAttribute(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } _converterType = converterType; } public JsonConverterAttribute(Type converterType, params object[] converterParameters) : this(converterType) { ConverterParameters = converterParameters; } } internal class JsonConverterCollection : Collection { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] internal sealed class JsonDictionaryAttribute : JsonContainerAttribute { public JsonDictionaryAttribute() { } public JsonDictionaryAttribute(string id) : base(id) { } } [Serializable] internal class JsonException : Exception { public JsonException() { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception? innerException) : base(message, innerException) { } public JsonException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) { message = JsonPosition.FormatMessage(lineInfo, path, message); return new JsonException(message); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] internal class JsonExtensionDataAttribute : Attribute { public bool WriteData { get; set; } public bool ReadData { get; set; } public JsonExtensionDataAttribute() { WriteData = true; ReadData = true; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] internal sealed class JsonIgnoreAttribute : Attribute { } internal abstract class JsonNameTable { public abstract string? Get(char[] key, int start, int length); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)] internal sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization; internal MissingMemberHandling? _missingMemberHandling; internal Required? _itemRequired; internal NullValueHandling? _itemNullValueHandling; public MemberSerialization MemberSerialization { get { return _memberSerialization; } set { _memberSerialization = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling.GetValueOrDefault(); } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired.GetValueOrDefault(); } set { _itemRequired = value; } } public JsonObjectAttribute() { } public JsonObjectAttribute(MemberSerialization memberSerialization) { MemberSerialization = memberSerialization; } public JsonObjectAttribute(string id) : base(id) { } } internal enum JsonContainerType { None, Object, Array, Constructor } internal struct JsonPosition { private static readonly char[] SpecialCharacters = new char[18] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; internal JsonContainerType Type; internal int Position; internal string? PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) { Type = type; HasIndex = TypeHasIndex(type); Position = -1; PropertyName = null; } internal int CalculateLength() { switch (Type) { case JsonContainerType.Object: return PropertyName.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; default: throw new ArgumentOutOfRangeException("Type"); } } internal void WriteTo(StringBuilder sb, ref StringWriter? writer, ref char[]? buffer) { switch (Type) { case JsonContainerType.Object: { string propertyName = PropertyName; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append("['"); if (writer == null) { writer = new StringWriter(sb); } JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer); sb.Append("']"); } else { if (sb.Length > 0) { sb.Append('.'); } sb.Append(propertyName); } break; } case JsonContainerType.Array: case JsonContainerType.Constructor: sb.Append('['); sb.Append(Position); sb.Append(']'); break; } } internal static bool TypeHasIndex(JsonContainerType type) { if (type != JsonContainerType.Array) { return type == JsonContainerType.Constructor; } return true; } internal static string BuildPath(List positions, JsonPosition? currentPosition) { int num = 0; if (positions != null) { for (int i = 0; i < positions.Count; i++) { num += positions[i].CalculateLength(); } } if (currentPosition.HasValue) { num += currentPosition.GetValueOrDefault().CalculateLength(); } StringBuilder stringBuilder = new StringBuilder(num); StringWriter writer = null; char[] buffer = null; if (positions != null) { foreach (JsonPosition position in positions) { position.WriteTo(stringBuilder, ref writer, ref buffer); } } currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer); return stringBuilder.ToString(); } internal static string FormatMessage(IJsonLineInfo? lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { message = message.Trim(); if (!StringUtils.EndsWith(message, '.')) { message += "."; } message += " "; } message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); if (lineInfo != null && lineInfo.HasLineInfo()) { message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); } message += "."; return message; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class JsonPropertyAttribute : Attribute { internal NullValueHandling? _nullValueHandling; internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal ObjectCreationHandling? _objectCreationHandling; internal TypeNameHandling? _typeNameHandling; internal bool? _isReference; internal int? _order; internal Required? _required; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; public Type? ItemConverterType { get; set; } public object[]? ItemConverterParameters { get; set; } public Type? NamingStrategyType { get; set; } public object[]? NamingStrategyParameters { get; set; } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public int Order { get { return _order.GetValueOrDefault(); } set { _order = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public string? PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public JsonPropertyAttribute() { } public JsonPropertyAttribute(string propertyName) { PropertyName = propertyName; } } internal abstract class JsonReader : IDisposable { protected internal enum State { Start, Complete, Property, ObjectStart, Object, ArrayStart, Array, Closed, PostValue, ConstructorStart, Constructor, Error, Finished } private JsonToken _tokenType; private object? _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; private CultureInfo? _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; private string? _dateFormatString; private List? _stack; protected State CurrentState => _currentState; public bool CloseInput { get; set; } public bool SupportMultipleContent { get; set; } public virtual char QuoteChar { get { return _quoteChar; } protected internal set { _quoteChar = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling; } set { if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset) { throw new ArgumentOutOfRangeException("value"); } _dateParseHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling; } set { if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) { throw new ArgumentOutOfRangeException("value"); } _floatParseHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; } } public virtual JsonToken TokenType => _tokenType; public virtual object? Value => _value; public virtual Type? ValueType => _value?.GetType(); public virtual int Depth { get { int num = _stack?.Count ?? 0; if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) { return num; } return num + 1; } } public virtual string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } public virtual Task ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Read().ToAsync(); } public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (TokenType == JsonToken.PropertyName) { await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth) { } } } internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken) { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedEndException(); } } public virtual Task ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsBoolean()); } public virtual Task ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsBytes()); } internal async Task ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) { List buffer = new List(); do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(buffer)); byte[] array = buffer.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } public virtual Task ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsDateTime()); } public virtual Task ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsDateTimeOffset()); } public virtual Task ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsDecimal()); } public virtual Task ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(ReadAsDouble()); } public virtual Task ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsInt32()); } public virtual Task ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync() ?? Task.FromResult(ReadAsString()); } internal async Task ReadAndMoveToContentAsync(CancellationToken cancellationToken) { bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (flag) { flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return flag; } internal Task MoveToContentAsync(CancellationToken cancellationToken) { JsonToken tokenType = TokenType; if (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { return MoveToContentFromNonContentAsync(cancellationToken); } return AsyncUtils.True; } private async Task MoveToContentFromNonContentAsync(CancellationToken cancellationToken) { JsonToken tokenType; do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } tokenType = TokenType; } while (tokenType == JsonToken.None || tokenType == JsonToken.Comment); return true; } internal JsonPosition GetPosition(int depth) { if (_stack != null && depth < _stack.Count) { return _stack[depth]; } return _currentPosition; } protected JsonReader() { _currentState = State.Start; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; _maxDepth = 64; CloseInput = true; } private void Push(JsonContainerType value) { UpdateScopeWithFinishedValue(); if (_currentPosition.Type == JsonContainerType.None) { _currentPosition = new JsonPosition(value); return; } if (_stack == null) { _stack = new List(); } _stack.Add(_currentPosition); _currentPosition = new JsonPosition(value); if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth) { return; } _hasExceededMaxDepth = true; throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); } private JsonContainerType Pop() { JsonPosition currentPosition; if (_stack != null && _stack.Count > 0) { currentPosition = _currentPosition; _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { currentPosition = _currentPosition; _currentPosition = default(JsonPosition); } if (_maxDepth.HasValue && Depth <= _maxDepth) { _hasExceededMaxDepth = false; } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract bool Read(); public virtual int? ReadAsInt32() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is int) { return (int)value; } int num; if (value is BigInteger bigInteger) { num = (int)bigInteger; } else { try { num = Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Integer, num, updateIndex: false); return num; } case JsonToken.String: { string s = (string)Value; return ReadInt32String(s); } default: throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal int? ReadInt32String(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (int.TryParse(s, NumberStyles.Integer, Culture, out var result)) { SetToken(JsonToken.Integer, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual string? ReadAsString() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.String: return (string)Value; default: if (JsonTokenUtils.IsPrimitiveToken(contentToken)) { object value = Value; if (value != null) { string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture)); SetToken(JsonToken.String, text, updateIndex: false); return text; } } throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } public virtual byte[]? ReadAsBytes() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.StartObject: { ReadIntoWrappedTypeObject(); byte[] array2 = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array2, updateIndex: false); return array2; } case JsonToken.String: { string text = (string)Value; Guid g; byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray())); SetToken(JsonToken.Bytes, array3, updateIndex: false); return array3; } case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Bytes: if (Value is Guid guid) { byte[] array = guid.ToByteArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } return (byte[])Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); default: throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal byte[] ReadArrayIntoByteArray() { List list = new List(); do { if (!Read()) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(list)); byte[] array = list.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } private bool ReadArrayElementIntoByteArrayReportDone(List buffer) { switch (TokenType) { case JsonToken.None: throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); case JsonToken.Integer: buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); return false; case JsonToken.EndArray: return true; case JsonToken.Comment: return false; default: throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } public virtual double? ReadAsDouble() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is double) { return (double)value; } double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger)); SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDoubleString((string)Value); default: throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal double? ReadDoubleString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual bool? ReadAsBoolean() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case JsonToken.String: return ReadBooleanString((string)Value); case JsonToken.Boolean: return (bool)Value; default: throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal bool? ReadBooleanString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (bool.TryParse(s, out var result)) { SetToken(JsonToken.Boolean, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual decimal? ReadAsDecimal() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; if (value is decimal) { return (decimal)value; } decimal num; if (value is BigInteger bigInteger) { num = (decimal)bigInteger; } else { try { num = Convert.ToDecimal(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDecimalString((string)Value); default: throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal decimal? ReadDecimalString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTime? ReadAsDateTime() { switch (GetContentToken()) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTimeOffset dateTimeOffset) { SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false); } return (DateTime)Value; case JsonToken.String: return ReadDateTimeString((string)Value); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTimeOffset? ReadAsDateTimeOffset() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTime dateTime) { SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false); } return (DateTimeOffset)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeOffsetString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal DateTimeOffset? ReadDateTimeOffsetString(string? s) { if (StringUtils.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } internal void ReaderReadAndAssert() { if (!Read()) { throw CreateUnexpectedEndException(); } } internal JsonReaderException CreateUnexpectedEndException() { return JsonReaderException.Create(this, "Unexpected end when reading JSON."); } internal void ReadIntoWrappedTypeObject() { ReaderReadAndAssert(); if (Value != null && Value.ToString() == "$type") { ReaderReadAndAssert(); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public void Skip() { if (TokenType == JsonToken.PropertyName) { Read(); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (Read() && depth < Depth) { } } } protected void SetToken(JsonToken newToken) { SetToken(newToken, null, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value) { SetToken(newToken, value, updateIndex: true); } protected void SetToken(JsonToken newToken, object? value, bool updateIndex) { _tokenType = newToken; _value = value; switch (newToken) { case JsonToken.StartObject: _currentState = State.ObjectStart; Push(JsonContainerType.Object); break; case JsonToken.StartArray: _currentState = State.ArrayStart; Push(JsonContainerType.Array); break; case JsonToken.StartConstructor: _currentState = State.ConstructorStart; Push(JsonContainerType.Constructor); break; case JsonToken.EndObject: ValidateEnd(JsonToken.EndObject); break; case JsonToken.EndArray: ValidateEnd(JsonToken.EndArray); break; case JsonToken.EndConstructor: ValidateEnd(JsonToken.EndConstructor); break; case JsonToken.PropertyName: _currentState = State.Property; _currentPosition.PropertyName = (string)value; break; case JsonToken.Raw: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: SetPostValueState(updateIndex); break; case JsonToken.Comment: break; } } internal void SetPostValueState(bool updateIndex) { if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } if (updateIndex) { UpdateScopeWithFinishedValue(); } } private void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void ValidateEnd(JsonToken endToken) { JsonContainerType jsonContainerType = Pop(); if (GetTypeForCloseToken(endToken) != jsonContainerType) { throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType)); } if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } } protected void SetStateBasedOnCurrent() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Constructor; break; case JsonContainerType.None: SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType)); } } private void SetFinished() { _currentState = ((!SupportMultipleContent) ? State.Finished : State.Start); } private JsonContainerType GetTypeForCloseToken(JsonToken token) { return token switch { JsonToken.EndObject => JsonContainerType.Object, JsonToken.EndArray => JsonContainerType.Array, JsonToken.EndConstructor => JsonContainerType.Constructor, _ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), }; } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } public virtual void Close() { _currentState = State.Closed; _tokenType = JsonToken.None; _value = null; } internal void ReadAndAssert() { if (!Read()) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal void ReadForTypeAndAssert(JsonContract? contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal bool ReadForType(JsonContract? contract, bool hasConverter) { if (hasConverter) { return Read(); } switch (contract?.InternalReadType ?? ReadType.Read) { case ReadType.Read: return ReadAndMoveToContent(); case ReadType.ReadAsInt32: ReadAsInt32(); break; case ReadType.ReadAsInt64: { bool result = ReadAndMoveToContent(); if (TokenType == JsonToken.Undefined) { throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long))); } return result; } case ReadType.ReadAsDecimal: ReadAsDecimal(); break; case ReadType.ReadAsDouble: ReadAsDouble(); break; case ReadType.ReadAsBytes: ReadAsBytes(); break; case ReadType.ReadAsBoolean: ReadAsBoolean(); break; case ReadType.ReadAsString: ReadAsString(); break; case ReadType.ReadAsDateTime: ReadAsDateTime(); break; case ReadType.ReadAsDateTimeOffset: ReadAsDateTimeOffset(); break; default: throw new ArgumentOutOfRangeException(); } return TokenType != JsonToken.None; } internal bool ReadAndMoveToContent() { if (Read()) { return MoveToContent(); } return false; } internal bool MoveToContent() { JsonToken tokenType = TokenType; while (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { if (!Read()) { return false; } tokenType = TokenType; } return true; } private JsonToken GetContentToken() { JsonToken tokenType; do { if (!Read()) { SetToken(JsonToken.None); return JsonToken.None; } tokenType = TokenType; } while (tokenType == JsonToken.Comment); return tokenType; } } [Serializable] internal class JsonReaderException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonReaderException() { } public JsonReaderException(string message) : base(message) { } public JsonReaderException(string message, Exception innerException) : base(message, innerException) { } public JsonReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonReaderException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonReaderException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonReaderException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonReaderException(message, path, lineNumber, linePosition, ex); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] internal sealed class JsonRequiredAttribute : Attribute { } [Serializable] internal class JsonSerializationException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string? Path { get; } public JsonSerializationException() { } public JsonSerializationException(string message) : base(message) { } public JsonSerializationException(string message, Exception innerException) : base(message, innerException) { } public JsonSerializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception? innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonSerializationException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonSerializationException Create(JsonReader reader, string message, Exception? ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonSerializationException Create(IJsonLineInfo? lineInfo, string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonSerializationException(message, path, lineNumber, linePosition, ex); } } internal class JsonSerializer { internal TypeNameHandling _typeNameHandling; internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; internal PreserveReferencesHandling _preserveReferencesHandling; internal ReferenceLoopHandling _referenceLoopHandling; internal MissingMemberHandling _missingMemberHandling; internal ObjectCreationHandling _objectCreationHandling; internal NullValueHandling _nullValueHandling; internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; internal JsonConverterCollection? _converters; internal IContractResolver _contractResolver; internal ITraceWriter? _traceWriter; internal IEqualityComparer? _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver? _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; private DateTimeZoneHandling? _dateTimeZoneHandling; private DateParseHandling? _dateParseHandling; private FloatFormatHandling? _floatFormatHandling; private FloatParseHandling? _floatParseHandling; private StringEscapeHandling? _stringEscapeHandling; private CultureInfo _culture; private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; private string? _dateFormatString; private bool _dateFormatStringSet; public virtual IReferenceResolver? ReferenceResolver { get { return GetReferenceResolver(); } set { if (value == null) { throw new ArgumentNullException("value", "Reference resolver cannot be null."); } _referenceResolver = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { get { if (_serializationBinder is SerializationBinder result) { return result; } if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value); } } public virtual ISerializationBinder SerializationBinder { get { return _serializationBinder; } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = value; } } public virtual ITraceWriter? TraceWriter { get { return _traceWriter; } set { _traceWriter = value; } } public virtual IEqualityComparer? EqualityComparer { get { return _equalityComparer; } set { _equalityComparer = value; } } public virtual TypeNameHandling TypeNameHandling { get { return _typeNameHandling; } set { if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) { throw new ArgumentOutOfRangeException("value"); } _typeNameHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public virtual FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; } set { if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling; } set { if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = value; } } public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } set { if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) { throw new ArgumentOutOfRangeException("value"); } _preserveReferencesHandling = value; } } public virtual ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling; } set { if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) { throw new ArgumentOutOfRangeException("value"); } _referenceLoopHandling = value; } } public virtual MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling; } set { if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _missingMemberHandling = value; } } public virtual NullValueHandling NullValueHandling { get { return _nullValueHandling; } set { if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _nullValueHandling = value; } } public virtual DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling; } set { if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) { throw new ArgumentOutOfRangeException("value"); } _defaultValueHandling = value; } } public virtual ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling; } set { if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) { throw new ArgumentOutOfRangeException("value"); } _objectCreationHandling = value; } } public virtual ConstructorHandling ConstructorHandling { get { return _constructorHandling; } set { if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) { throw new ArgumentOutOfRangeException("value"); } _constructorHandling = value; } } public virtual MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling; } set { if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _metadataPropertyHandling = value; } } public virtual JsonConverterCollection Converters { get { if (_converters == null) { _converters = new JsonConverterCollection(); } return _converters; } } public virtual IContractResolver ContractResolver { get { return _contractResolver; } set { _contractResolver = value ?? DefaultContractResolver.Instance; } } public virtual StreamingContext Context { get { return _context; } set { _context = value; } } public virtual Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public virtual DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public virtual FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public virtual string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public virtual CultureInfo Culture { get { return _culture ?? JsonSerializerSettings.DefaultCulture; } set { _culture = value; } } public virtual int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public virtual bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } public virtual event EventHandler? Error; internal bool IsCheckAdditionalContentSet() { return _checkAdditionalContent.HasValue; } public JsonSerializer() { _referenceLoopHandling = ReferenceLoopHandling.Error; _missingMemberHandling = MissingMemberHandling.Ignore; _nullValueHandling = NullValueHandling.Include; _defaultValueHandling = DefaultValueHandling.Include; _objectCreationHandling = ObjectCreationHandling.Auto; _preserveReferencesHandling = PreserveReferencesHandling.None; _constructorHandling = ConstructorHandling.Default; _typeNameHandling = TypeNameHandling.None; _metadataPropertyHandling = MetadataPropertyHandling.Default; _context = JsonSerializerSettings.DefaultContext; _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; } public static JsonSerializer Create() { return new JsonSerializer(); } public static JsonSerializer Create(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = Create(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } public static JsonSerializer CreateDefault() { return Create(JsonConvert.DefaultSettings?.Invoke()); } public static JsonSerializer CreateDefault(JsonSerializerSettings? settings) { JsonSerializer jsonSerializer = CreateDefault(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) { if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) { for (int i = 0; i < settings.Converters.Count; i++) { serializer.Converters.Insert(i, settings.Converters[i]); } } if (settings._typeNameHandling.HasValue) { serializer.TypeNameHandling = settings.TypeNameHandling; } if (settings._metadataPropertyHandling.HasValue) { serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; } if (settings._typeNameAssemblyFormatHandling.HasValue) { serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; } if (settings._preserveReferencesHandling.HasValue) { serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; } if (settings._referenceLoopHandling.HasValue) { serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; } if (settings._missingMemberHandling.HasValue) { serializer.MissingMemberHandling = settings.MissingMemberHandling; } if (settings._objectCreationHandling.HasValue) { serializer.ObjectCreationHandling = settings.ObjectCreationHandling; } if (settings._nullValueHandling.HasValue) { serializer.NullValueHandling = settings.NullValueHandling; } if (settings._defaultValueHandling.HasValue) { serializer.DefaultValueHandling = settings.DefaultValueHandling; } if (settings._constructorHandling.HasValue) { serializer.ConstructorHandling = settings.ConstructorHandling; } if (settings._context.HasValue) { serializer.Context = settings.Context; } if (settings._checkAdditionalContent.HasValue) { serializer._checkAdditionalContent = settings._checkAdditionalContent; } if (settings.Error != null) { serializer.Error += settings.Error; } if (settings.ContractResolver != null) { serializer.ContractResolver = settings.ContractResolver; } if (settings.ReferenceResolverProvider != null) { serializer.ReferenceResolver = settings.ReferenceResolverProvider(); } if (settings.TraceWriter != null) { serializer.TraceWriter = settings.TraceWriter; } if (settings.EqualityComparer != null) { serializer.EqualityComparer = settings.EqualityComparer; } if (settings.SerializationBinder != null) { serializer.SerializationBinder = settings.SerializationBinder; } if (settings._formatting.HasValue) { serializer._formatting = settings._formatting; } if (settings._dateFormatHandling.HasValue) { serializer._dateFormatHandling = settings._dateFormatHandling; } if (settings._dateTimeZoneHandling.HasValue) { serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; } if (settings._dateParseHandling.HasValue) { serializer._dateParseHandling = settings._dateParseHandling; } if (settings._dateFormatStringSet) { serializer._dateFormatString = settings._dateFormatString; serializer._dateFormatStringSet = settings._dateFormatStringSet; } if (settings._floatFormatHandling.HasValue) { serializer._floatFormatHandling = settings._floatFormatHandling; } if (settings._floatParseHandling.HasValue) { serializer._floatParseHandling = settings._floatParseHandling; } if (settings._stringEscapeHandling.HasValue) { serializer._stringEscapeHandling = settings._stringEscapeHandling; } if (settings._culture != null) { serializer._culture = settings._culture; } if (settings._maxDepthSet) { serializer._maxDepth = settings._maxDepth; serializer._maxDepthSet = settings._maxDepthSet; } } [DebuggerStepThrough] public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } [DebuggerStepThrough] public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); } internal virtual void PopulateInternal(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader) { return Deserialize(reader, null); } [DebuggerStepThrough] public object? Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } [DebuggerStepThrough] public T? Deserialize(JsonReader reader) { return (T)Deserialize(reader, typeof(T)); } [DebuggerStepThrough] public object? Deserialize(JsonReader reader, Type? objectType) { return DeserializeInternal(reader, objectType); } internal virtual object? DeserializeInternal(JsonReader reader, Type? objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); SetupReader(reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); object? result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); return result; } internal void SetupReader(JsonReader reader, out CultureInfo? previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string? previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture; } else { previousCulture = null; } if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling = reader.DateTimeZoneHandling; reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } else { previousDateTimeZoneHandling = null; } if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling) { previousDateParseHandling = reader.DateParseHandling; reader.DateParseHandling = _dateParseHandling.GetValueOrDefault(); } else { previousDateParseHandling = null; } if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling) { previousFloatParseHandling = reader.FloatParseHandling; reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault(); } else { previousFloatParseHandling = null; } if (_maxDepthSet && reader.MaxDepth != _maxDepth) { previousMaxDepth = reader.MaxDepth; reader.MaxDepth = _maxDepth; } else { previousMaxDepth = null; } if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) { previousDateFormatString = reader.DateFormatString; reader.DateFormatString = _dateFormatString; } else { previousDateFormatString = null; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver) { jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable(); } } private void ResetReader(JsonReader reader, CultureInfo? previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string? previousDateFormatString) { if (previousCulture != null) { reader.Culture = previousCulture; } if (previousDateTimeZoneHandling.HasValue) { reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault(); } if (previousDateParseHandling.HasValue) { reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault(); } if (previousFloatParseHandling.HasValue) { reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault(); } if (_maxDepthSet) { reader.MaxDepth = previousMaxDepth; } if (_dateFormatStringSet) { reader.DateFormatString = previousDateFormatString; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable()) { jsonTextReader.PropertyNameTable = null; } } public void Serialize(TextWriter textWriter, object? value) { Serialize(new JsonTextWriter(textWriter), value); } public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { SerializeInternal(jsonWriter, value, objectType); } public void Serialize(TextWriter textWriter, object? value, Type objectType) { Serialize(new JsonTextWriter(textWriter), value, objectType); } public void Serialize(JsonWriter jsonWriter, object? value) { SerializeInternal(jsonWriter, value, null); } private TraceJsonReader CreateTraceJsonReader(JsonReader reader) { TraceJsonReader traceJsonReader = new TraceJsonReader(reader); if (reader.TokenType != 0) { traceJsonReader.WriteCurrentToken(); } return traceJsonReader; } internal virtual void SerializeInternal(JsonWriter jsonWriter, object? value, Type? objectType) { ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter"); Formatting? formatting = null; if (_formatting.HasValue && jsonWriter.Formatting != _formatting) { formatting = jsonWriter.Formatting; jsonWriter.Formatting = _formatting.GetValueOrDefault(); } DateFormatHandling? dateFormatHandling = null; if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling) { dateFormatHandling = jsonWriter.DateFormatHandling; jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault(); } DateTimeZoneHandling? dateTimeZoneHandling = null; if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling) { dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling; jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } FloatFormatHandling? floatFormatHandling = null; if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling) { floatFormatHandling = jsonWriter.FloatFormatHandling; jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault(); } StringEscapeHandling? stringEscapeHandling = null; if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling) { stringEscapeHandling = jsonWriter.StringEscapeHandling; jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); } CultureInfo cultureInfo = null; if (_culture != null && !_culture.Equals(jsonWriter.Culture)) { cultureInfo = jsonWriter.Culture; jsonWriter.Culture = _culture; } string dateFormatString = null; if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) { dateFormatString = jsonWriter.DateFormatString; jsonWriter.DateFormatString = _dateFormatString; } TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null); new JsonSerializerInternalWriter(this).Serialize(traceJsonWriter ?? jsonWriter, value, objectType); if (traceJsonWriter != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); } if (formatting.HasValue) { jsonWriter.Formatting = formatting.GetValueOrDefault(); } if (dateFormatHandling.HasValue) { jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault(); } if (dateTimeZoneHandling.HasValue) { jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault(); } if (floatFormatHandling.HasValue) { jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault(); } if (stringEscapeHandling.HasValue) { jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault(); } if (_dateFormatStringSet) { jsonWriter.DateFormatString = dateFormatString; } if (cultureInfo != null) { jsonWriter.Culture = cultureInfo; } } internal IReferenceResolver GetReferenceResolver() { if (_referenceResolver == null) { _referenceResolver = new DefaultReferenceResolver(); } return _referenceResolver; } internal JsonConverter? GetMatchingConverter(Type type) { return GetMatchingConverter(_converters, type); } internal static JsonConverter? GetMatchingConverter(IList? converters, Type objectType) { if (converters != null) { for (int i = 0; i < converters.Count; i++) { JsonConverter jsonConverter = converters[i]; if (jsonConverter.CanConvert(objectType)) { return jsonConverter; } } } return null; } internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e) { this.Error?.Invoke(this, e); } } internal class JsonSerializerSettings { internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error; internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore; internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include; internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include; internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto; internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default; internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default; internal static readonly StreamingContext DefaultContext; internal const Formatting DefaultFormatting = Formatting.None; internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat; internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime; internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double; internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String; internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default; internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; internal static readonly CultureInfo DefaultCulture; internal const bool DefaultCheckAdditionalContent = false; internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; internal const int DefaultMaxDepth = 64; internal Formatting? _formatting; internal DateFormatHandling? _dateFormatHandling; internal DateTimeZoneHandling? _dateTimeZoneHandling; internal DateParseHandling? _dateParseHandling; internal FloatFormatHandling? _floatFormatHandling; internal FloatParseHandling? _floatParseHandling; internal StringEscapeHandling? _stringEscapeHandling; internal CultureInfo? _culture; internal bool? _checkAdditionalContent; internal int? _maxDepth; internal bool _maxDepthSet; internal string? _dateFormatString; internal bool _dateFormatStringSet; internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; internal DefaultValueHandling? _defaultValueHandling; internal PreserveReferencesHandling? _preserveReferencesHandling; internal NullValueHandling? _nullValueHandling; internal ObjectCreationHandling? _objectCreationHandling; internal MissingMemberHandling? _missingMemberHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal StreamingContext? _context; internal ConstructorHandling? _constructorHandling; internal TypeNameHandling? _typeNameHandling; internal MetadataPropertyHandling? _metadataPropertyHandling; public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public IList Converters { get; set; } public PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling.GetValueOrDefault(); } set { _preserveReferencesHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling.GetValueOrDefault(); } set { _metadataPropertyHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)TypeNameAssemblyFormatHandling; } set { TypeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling.GetValueOrDefault(); } set { _typeNameAssemblyFormatHandling = value; } } public ConstructorHandling ConstructorHandling { get { return _constructorHandling.GetValueOrDefault(); } set { _constructorHandling = value; } } public IContractResolver? ContractResolver { get; set; } public IEqualityComparer? EqualityComparer { get; set; } [Obsolete("ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")] public IReferenceResolver? ReferenceResolver { get { return ReferenceResolverProvider?.Invoke(); } set { IReferenceResolver value2 = value; ReferenceResolverProvider = ((value2 != null) ? ((Func)(() => value2)) : null); } } public Func? ReferenceResolverProvider { get; set; } public ITraceWriter? TraceWriter { get; set; } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public SerializationBinder? Binder { get { if (SerializationBinder == null) { return null; } if (SerializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { SerializationBinder = ((value == null) ? null : new SerializationBinderAdapter(value)); } } public ISerializationBinder? SerializationBinder { get; set; } public EventHandler? Error { get; set; } public StreamingContext Context { get { return _context ?? DefaultContext; } set { _context = value; } } public string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public int? MaxDepth { get { if (!_maxDepthSet) { return 64; } return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public Formatting Formatting { get { return _formatting.GetValueOrDefault(); } set { _formatting = value; } } public DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } set { _dateFormatHandling = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling.GetValueOrDefault(); } set { _floatParseHandling = value; } } public StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } set { _stringEscapeHandling = value; } } public CultureInfo Culture { get { return _culture ?? DefaultCulture; } set { _culture = value; } } public bool CheckAdditionalContent { get { return _checkAdditionalContent.GetValueOrDefault(); } set { _checkAdditionalContent = value; } } static JsonSerializerSettings() { DefaultContext = default(StreamingContext); DefaultCulture = CultureInfo.InvariantCulture; } [DebuggerStepThrough] public JsonSerializerSettings() { Converters = new List(); } public JsonSerializerSettings(JsonSerializerSettings original) { _floatParseHandling = original._floatParseHandling; _floatFormatHandling = original._floatFormatHandling; _dateParseHandling = original._dateParseHandling; _dateTimeZoneHandling = original._dateTimeZoneHandling; _dateFormatHandling = original._dateFormatHandling; _formatting = original._formatting; _maxDepth = original._maxDepth; _maxDepthSet = original._maxDepthSet; _dateFormatString = original._dateFormatString; _dateFormatStringSet = original._dateFormatStringSet; _context = original._context; Error = original.Error; SerializationBinder = original.SerializationBinder; TraceWriter = original.TraceWriter; _culture = original._culture; ReferenceResolverProvider = original.ReferenceResolverProvider; EqualityComparer = original.EqualityComparer; ContractResolver = original.ContractResolver; _constructorHandling = original._constructorHandling; _typeNameAssemblyFormatHandling = original._typeNameAssemblyFormatHandling; _metadataPropertyHandling = original._metadataPropertyHandling; _typeNameHandling = original._typeNameHandling; _preserveReferencesHandling = original._preserveReferencesHandling; Converters = original.Converters.ToList(); _defaultValueHandling = original._defaultValueHandling; _nullValueHandling = original._nullValueHandling; _objectCreationHandling = original._objectCreationHandling; _missingMemberHandling = original._missingMemberHandling; _referenceLoopHandling = original._referenceLoopHandling; _checkAdditionalContent = original._checkAdditionalContent; _stringEscapeHandling = original._stringEscapeHandling; } } internal class JsonTextReader : JsonReader, IJsonLineInfo { private readonly bool _safeAsync; private const char UnicodeReplacementChar = '\ufffd'; private const int MaximumJavascriptIntegerCharacterLength = 380; private const int LargeBufferLength = 1073741823; private readonly TextReader _reader; private char[]? _chars; private int _charsUsed; private int _charPos; private int _lineStartPos; private int _lineNumber; private bool _isEndOfFile; private StringBuffer _stringBuffer; private StringReference _stringReference; private IArrayPool? _arrayPool; public JsonNameTable? PropertyNameTable { get; set; } public IArrayPool? ArrayPool { get { return _arrayPool; } set { if (value == null) { throw new ArgumentNullException("value"); } _arrayPool = value; } } public int LineNumber { get { if (base.CurrentState == State.Start && LinePosition == 0 && TokenType != JsonToken.Comment) { return 0; } return _lineNumber; } } public int LinePosition => _charPos - _lineStartPos; public override Task ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsync(cancellationToken); } return DoReadAsync(cancellationToken); } internal Task DoReadAsync(CancellationToken cancellationToken) { EnsureBuffer(); Task task; do { switch (_currentState) { case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: return ParseValueAsync(cancellationToken); case State.ObjectStart: case State.Object: return ParseObjectAsync(cancellationToken); case State.PostValue: task = ParsePostValueAsync(ignoreComments: false, cancellationToken); if (!task.IsCompletedSuccessfully()) { return DoReadAsync(task, cancellationToken); } break; case State.Finished: return ReadFromFinishedAsync(cancellationToken); default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } while (!task.Result); return AsyncUtils.True; } private async Task DoReadAsync(Task task, CancellationToken cancellationToken) { if (await task.ConfigureAwait(continueOnCapturedContext: false)) { return true; } return await DoReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } private async Task ParsePostValueAsync(bool ignoreComments, CancellationToken cancellationToken) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { _currentState = State.Finished; return false; } } else { _charPos++; } continue; case '}': _charPos++; SetToken(JsonToken.EndObject); return true; case ']': _charPos++; SetToken(JsonToken.EndArray); return true; case ')': _charPos++; SetToken(JsonToken.EndConstructor); return true; case '/': await ParseCommentAsync(!ignoreComments, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!ignoreComments) { return true; } continue; case ',': _charPos++; SetStateBasedOnCurrent(); return false; case '\t': case ' ': _charPos++; continue; case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); continue; case '\n': ProcessLineFeed(); continue; } if (char.IsWhiteSpace(c)) { _charPos++; continue; } if (base.SupportMultipleContent && Depth == 0) { SetStateBasedOnCurrent(); return false; } throw JsonReaderException.Create(this, "After parsing a value an unexpected character was encountered: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } } private async Task ReadFromFinishedAsync(CancellationToken cancellationToken) { if (await EnsureCharsAsync(0, append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_isEndOfFile) { SetToken(JsonToken.None); return false; } if (_chars[_charPos] == '/') { await ParseCommentAsync(setToken: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; } throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } SetToken(JsonToken.None); return false; } private Task ReadDataAsync(bool append, CancellationToken cancellationToken) { return ReadDataAsync(append, 0, cancellationToken); } private async Task ReadDataAsync(bool append, int charsRequired, CancellationToken cancellationToken) { if (_isEndOfFile) { return 0; } PrepareBufferForReadData(append, charsRequired); int num = await _reader.ReadAsync(_chars, _charsUsed, _chars.Length - _charsUsed - 1, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); _charsUsed += num; if (num == 0) { _isEndOfFile = true; } _chars[_charsUsed] = '\0'; return num; } private async Task ParseValueAsync(CancellationToken cancellationToken) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { return false; } } else { _charPos++; } break; case '"': case '\'': await ParseStringAsync(c, ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 't': await ParseTrueAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 'f': await ParseFalseAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 'n': if (await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { switch (_chars[_charPos + 1]) { case 'u': await ParseNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case 'e': await ParseConstructorAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; default: throw CreateUnexpectedCharacterException(_chars[_charPos]); } return true; } _charPos++; throw CreateUnexpectedEndException(); case 'N': await ParseNumberNaNAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 'I': await ParseNumberPositiveInfinityAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case '-': if (!(await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) || _chars[_charPos + 1] != 'I') { await ParseNumberAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { await ParseNumberNegativeInfinityAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return true; case '/': await ParseCommentAsync(setToken: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case 'u': await ParseUndefinedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case '{': _charPos++; SetToken(JsonToken.StartObject); return true; case '[': _charPos++; SetToken(JsonToken.StartArray); return true; case ']': _charPos++; SetToken(JsonToken.EndArray); return true; case ',': SetToken(JsonToken.Undefined); return true; case ')': _charPos++; SetToken(JsonToken.EndConstructor); return true; case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: if (char.IsWhiteSpace(c)) { _charPos++; break; } if (char.IsNumber(c) || c == '-' || c == '.') { await ParseNumberAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; } throw CreateUnexpectedCharacterException(c); } } } private async Task ReadStringIntoBufferAsync(char quote, CancellationToken cancellationToken) { int charPos = _charPos; int initialPosition = _charPos; int lastWritePosition = _charPos; _stringBuffer.Position = 0; while (true) { switch (_chars[charPos++]) { case '\0': if (_charsUsed == charPos - 1) { charPos--; if (await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { _charPos = charPos; throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } } break; case '\\': { _charPos = charPos; if (!(await EnsureCharsAsync(0, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } int escapeStartPos = charPos - 1; char c = _chars[charPos]; charPos++; char writeChar; switch (c) { case 'b': writeChar = '\b'; break; case 't': writeChar = '\t'; break; case 'n': writeChar = '\n'; break; case 'f': writeChar = '\f'; break; case 'r': writeChar = '\r'; break; case '\\': writeChar = '\\'; break; case '"': case '\'': case '/': writeChar = c; break; case 'u': _charPos = charPos; writeChar = await ParseUnicodeAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (StringUtils.IsLowSurrogate(writeChar)) { writeChar = '\ufffd'; } else if (StringUtils.IsHighSurrogate(writeChar)) { bool anotherHighSurrogate; do { anotherHighSurrogate = false; if (await EnsureCharsAsync(2, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && _chars[_charPos] == '\\' && _chars[_charPos + 1] == 'u') { char highSurrogate = writeChar; _charPos += 2; writeChar = await ParseUnicodeAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!StringUtils.IsLowSurrogate(writeChar)) { if (StringUtils.IsHighSurrogate(writeChar)) { highSurrogate = '\ufffd'; anotherHighSurrogate = true; } else { highSurrogate = '\ufffd'; } } EnsureBufferNotEmpty(); WriteCharToBuffer(highSurrogate, lastWritePosition, escapeStartPos); lastWritePosition = _charPos; } else { writeChar = '\ufffd'; } } while (anotherHighSurrogate); } charPos = _charPos; break; default: _charPos = charPos; throw JsonReaderException.Create(this, "Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, "\\" + c)); } EnsureBufferNotEmpty(); WriteCharToBuffer(writeChar, lastWritePosition, escapeStartPos); lastWritePosition = charPos; break; } case '\r': _charPos = charPos - 1; await ProcessCarriageReturnAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); charPos = _charPos; break; case '\n': _charPos = charPos - 1; ProcessLineFeed(); charPos = _charPos; break; case '"': case '\'': if (_chars[charPos - 1] == quote) { FinishReadStringIntoBuffer(charPos - 1, initialPosition, lastWritePosition); return; } break; } } } private Task ProcessCarriageReturnAsync(bool append, CancellationToken cancellationToken) { _charPos++; Task task = EnsureCharsAsync(1, append, cancellationToken); if (task.IsCompletedSuccessfully()) { SetNewLine(task.Result); return AsyncUtils.CompletedTask; } return ProcessCarriageReturnAsync(task); } private async Task ProcessCarriageReturnAsync(Task task) { SetNewLine(await task.ConfigureAwait(continueOnCapturedContext: false)); } private async Task ParseUnicodeAsync(CancellationToken cancellationToken) { return ConvertUnicode(await EnsureCharsAsync(4, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } private Task EnsureCharsAsync(int relativePosition, bool append, CancellationToken cancellationToken) { if (_charPos + relativePosition < _charsUsed) { return AsyncUtils.True; } if (_isEndOfFile) { return AsyncUtils.False; } return ReadCharsAsync(relativePosition, append, cancellationToken); } private async Task ReadCharsAsync(int relativePosition, bool append, CancellationToken cancellationToken) { int charsRequired = _charPos + relativePosition - _charsUsed + 1; do { int num = await ReadDataAsync(append, charsRequired, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (num == 0) { return false; } charsRequired -= num; } while (charsRequired > 0); return true; } private async Task ParseObjectAsync(CancellationToken cancellationToken) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { return false; } } else { _charPos++; } break; case '}': SetToken(JsonToken.EndObject); _charPos++; return true; case '/': await ParseCommentAsync(setToken: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return true; case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: if (char.IsWhiteSpace(c)) { _charPos++; break; } return await ParsePropertyAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } } private async Task ParseCommentAsync(bool setToken, CancellationToken cancellationToken) { _charPos++; if (!(await EnsureCharsAsync(1, append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); } bool singlelineComment; if (_chars[_charPos] == '*') { singlelineComment = false; } else { if (_chars[_charPos] != '/') { throw JsonReaderException.Create(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } singlelineComment = true; } _charPos++; int initialPosition = _charPos; while (true) { switch (_chars[_charPos]) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { if (!singlelineComment) { throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); } EndComment(setToken, initialPosition, _charPos); return; } } else { _charPos++; } break; case '*': _charPos++; if (!singlelineComment && await EnsureCharsAsync(0, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && _chars[_charPos] == '/') { EndComment(setToken, initialPosition, _charPos - 1); _charPos++; return; } break; case '\r': if (singlelineComment) { EndComment(setToken, initialPosition, _charPos); return; } await ProcessCarriageReturnAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': if (singlelineComment) { EndComment(setToken, initialPosition, _charPos); return; } ProcessLineFeed(); break; default: _charPos++; break; } } } private async Task EatWhitespaceAsync(CancellationToken cancellationToken) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { return; } } else { _charPos++; } break; case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; default: if (!char.IsWhiteSpace(c)) { return; } goto case ' '; case ' ': _charPos++; break; } } } private async Task ParseStringAsync(char quote, ReadType readType, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); _charPos++; ShiftBufferIfNeeded(); await ReadStringIntoBufferAsync(quote, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); ParseReadString(quote, readType); } private async Task MatchValueAsync(string value, CancellationToken cancellationToken) { return MatchValue(await EnsureCharsAsync(value.Length - 1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false), value); } private async Task MatchValueWithTrailingSeparatorAsync(string value, CancellationToken cancellationToken) { if (!(await MatchValueAsync(value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } if (!(await EnsureCharsAsync(0, append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return true; } return IsSeparator(_chars[_charPos]) || _chars[_charPos] == '\0'; } private async Task MatchAndSetAsync(string value, JsonToken newToken, object? tokenValue, CancellationToken cancellationToken) { if (await MatchValueWithTrailingSeparatorAsync(value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(newToken, tokenValue); return; } throw JsonReaderException.Create(this, "Error parsing " + newToken.ToString().ToLowerInvariant() + " value."); } private Task ParseTrueAsync(CancellationToken cancellationToken) { return MatchAndSetAsync(JsonConvert.True, JsonToken.Boolean, true, cancellationToken); } private Task ParseFalseAsync(CancellationToken cancellationToken) { return MatchAndSetAsync(JsonConvert.False, JsonToken.Boolean, false, cancellationToken); } private Task ParseNullAsync(CancellationToken cancellationToken) { return MatchAndSetAsync(JsonConvert.Null, JsonToken.Null, null, cancellationToken); } private async Task ParseConstructorAsync(CancellationToken cancellationToken) { if (await MatchValueWithTrailingSeparatorAsync("new", cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); int initialPosition = _charPos; int endPosition; while (true) { char c = _chars[_charPos]; if (c == '\0') { if (_charsUsed == _charPos) { if (await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { throw JsonReaderException.Create(this, "Unexpected end while parsing constructor."); } continue; } endPosition = _charPos; _charPos++; break; } if (char.IsLetterOrDigit(c)) { _charPos++; continue; } switch (c) { case '\r': endPosition = _charPos; await ProcessCarriageReturnAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': endPosition = _charPos; ProcessLineFeed(); break; default: if (char.IsWhiteSpace(c)) { endPosition = _charPos; _charPos++; break; } if (c == '(') { endPosition = _charPos; break; } throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } break; } _stringReference = new StringReference(_chars, initialPosition, endPosition - initialPosition); string constructorName = _stringReference.ToString(); await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_chars[_charPos] != '(') { throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } _charPos++; ClearRecentString(); SetToken(JsonToken.StartConstructor, constructorName); return; } throw JsonReaderException.Create(this, "Unexpected content while parsing JSON."); } private async Task ParseNumberNaNAsync(ReadType readType, CancellationToken cancellationToken) { return ParseNumberNaN(readType, await MatchValueWithTrailingSeparatorAsync(JsonConvert.NaN, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } private async Task ParseNumberPositiveInfinityAsync(ReadType readType, CancellationToken cancellationToken) { return ParseNumberPositiveInfinity(readType, await MatchValueWithTrailingSeparatorAsync(JsonConvert.PositiveInfinity, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } private async Task ParseNumberNegativeInfinityAsync(ReadType readType, CancellationToken cancellationToken) { return ParseNumberNegativeInfinity(readType, await MatchValueWithTrailingSeparatorAsync(JsonConvert.NegativeInfinity, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } private async Task ParseNumberAsync(ReadType readType, CancellationToken cancellationToken) { ShiftBufferIfNeeded(); char firstChar = _chars[_charPos]; int initialPosition = _charPos; await ReadNumberIntoBufferAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); ParseReadNumber(readType, firstChar, initialPosition); } private Task ParseUndefinedAsync(CancellationToken cancellationToken) { return MatchAndSetAsync(JsonConvert.Undefined, JsonToken.Undefined, null, cancellationToken); } private async Task ParsePropertyAsync(CancellationToken cancellationToken) { char c = _chars[_charPos]; char quoteChar; if (c == '"' || c == '\'') { _charPos++; quoteChar = c; ShiftBufferIfNeeded(); await ReadStringIntoBufferAsync(quoteChar, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { if (!ValidIdentifierChar(c)) { throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } quoteChar = '\0'; ShiftBufferIfNeeded(); await ParseUnquotedPropertyAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } string propertyName = ((PropertyNameTable == null) ? _stringReference.ToString() : (PropertyNameTable.Get(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length) ?? _stringReference.ToString())); await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_chars[_charPos] != ':') { throw JsonReaderException.Create(this, "Invalid character after parsing property name. Expected ':' but got: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } _charPos++; SetToken(JsonToken.PropertyName, propertyName); _quoteChar = quoteChar; ClearRecentString(); return true; } private async Task ReadNumberIntoBufferAsync(CancellationToken cancellationToken) { int charPos = _charPos; while (true) { char c = _chars[charPos]; if (c == '\0') { _charPos = charPos; if (_charsUsed != charPos || await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { break; } } else { if (ReadNumberCharIntoBuffer(c, charPos)) { break; } charPos++; } } } private async Task ParseUnquotedPropertyAsync(CancellationToken cancellationToken) { int initialPosition = _charPos; while (true) { char c = _chars[_charPos]; if (c == '\0') { if (_charsUsed != _charPos) { _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition); break; } if (await ReadDataAsync(append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { throw JsonReaderException.Create(this, "Unexpected end while parsing unquoted property name."); } } else if (ReadUnquotedPropertyReportIfDone(c, initialPosition)) { break; } } } private async Task ReadNullCharAsync(CancellationToken cancellationToken) { if (_charsUsed == _charPos) { if (await ReadDataAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) == 0) { _isEndOfFile = true; return true; } } else { _charPos++; } return false; } private async Task HandleNullAsync(CancellationToken cancellationToken) { if (await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { if (_chars[_charPos + 1] == 'u') { await ParseNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return; } _charPos += 2; throw CreateUnexpectedCharacterException(_chars[_charPos - 1]); } _charPos = _charsUsed; throw CreateUnexpectedEndException(); } private async Task ReadFinishedAsync(CancellationToken cancellationToken) { if (await EnsureCharsAsync(0, append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { await EatWhitespaceAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_isEndOfFile) { SetToken(JsonToken.None); return; } if (_chars[_charPos] != '/') { throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } SetToken(JsonToken.None); } private async Task ReadStringValueAsync(ReadType readType, CancellationToken cancellationToken) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (await ParsePostValueAsync(ignoreComments: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': await ParseStringAsync(c, readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return FinishReadQuotedStringValue(readType); case '-': if (await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && _chars[_charPos + 1] == 'I') { return ParseNumberNegativeInfinity(readType); } await ParseNumberAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return Value; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (readType != ReadType.ReadAsString) { _charPos++; throw CreateUnexpectedCharacterException(c); } await ParseNumberAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return Value; case 'f': case 't': { if (readType != ReadType.ReadAsString) { _charPos++; throw CreateUnexpectedCharacterException(c); } string expected = ((c == 't') ? JsonConvert.True : JsonConvert.False); if (!(await MatchValueWithTrailingSeparatorAsync(expected, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedCharacterException(_chars[_charPos]); } SetToken(JsonToken.String, expected); return expected; } case 'I': return await ParseNumberPositiveInfinityAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case 'N': return await ParseNumberNaNAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case 'n': await HandleNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; case '/': await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: await ReadFinishedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private async Task ReadNumberValueAsync(ReadType readType, CancellationToken cancellationToken) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (await ParsePostValueAsync(ignoreComments: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': await ParseStringAsync(c, readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return FinishReadQuotedNumber(readType); case 'n': await HandleNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; case 'N': return await ParseNumberNaNAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case 'I': return await ParseNumberPositiveInfinityAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case '-': if (await EnsureCharsAsync(1, append: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && _chars[_charPos + 1] == 'I') { return await ParseNumberNegativeInfinityAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await ParseNumberAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return Value; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': await ParseNumberAsync(readType, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return Value; case '/': await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: await ReadFinishedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } public override Task ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsBooleanAsync(cancellationToken); } return DoReadAsBooleanAsync(cancellationToken); } internal async Task DoReadAsBooleanAsync(CancellationToken cancellationToken) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (await ParsePostValueAsync(ignoreComments: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': await ParseStringAsync(c, ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return ReadBooleanString(_stringReference.ToString()); case 'n': await HandleNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { await ParseNumberAsync(ReadType.Read, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); bool flag = ((!(Value is BigInteger i)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (i != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case 'f': case 't': { bool isTrue = c == 't'; if (!(await MatchValueWithTrailingSeparatorAsync(isTrue ? JsonConvert.True : JsonConvert.False, cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedCharacterException(_chars[_charPos]); } SetToken(JsonToken.Boolean, isTrue); return isTrue; } case '/': await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: await ReadFinishedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } public override Task ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsBytesAsync(cancellationToken); } return DoReadAsBytesAsync(cancellationToken); } internal async Task DoReadAsBytesAsync(CancellationToken cancellationToken) { EnsureBuffer(); bool isWrapped = false; switch (_currentState) { case State.PostValue: if (await ParsePostValueAsync(ignoreComments: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (await ReadNullCharAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': { await ParseStringAsync(c, ReadType.ReadAsBytes, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); byte[] data = (byte[])Value; if (isWrapped) { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, data, updateIndex: false); } return data; } case '{': _charPos++; SetToken(JsonToken.StartObject); await ReadIntoWrappedTypeObjectAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); isWrapped = true; break; case '[': _charPos++; SetToken(JsonToken.StartArray); return await ReadArrayIntoByteArrayAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case 'n': await HandleNullAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; case '/': await ParseCommentAsync(setToken: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': await ProcessCarriageReturnAsync(append: false, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: await ReadFinishedAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private async Task ReadIntoWrappedTypeObjectAsync(CancellationToken cancellationToken) { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (Value != null && Value.ToString() == "$type") { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { await ReaderReadAndAssertAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public override Task ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsDateTimeAsync(cancellationToken); } return DoReadAsDateTimeAsync(cancellationToken); } internal async Task DoReadAsDateTimeAsync(CancellationToken cancellationToken) { return (DateTime?)(await ReadStringValueAsync(ReadType.ReadAsDateTime, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsDateTimeOffsetAsync(cancellationToken); } return DoReadAsDateTimeOffsetAsync(cancellationToken); } internal async Task DoReadAsDateTimeOffsetAsync(CancellationToken cancellationToken) { return (DateTimeOffset?)(await ReadStringValueAsync(ReadType.ReadAsDateTimeOffset, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsDecimalAsync(cancellationToken); } return DoReadAsDecimalAsync(cancellationToken); } internal async Task DoReadAsDecimalAsync(CancellationToken cancellationToken) { return (decimal?)(await ReadNumberValueAsync(ReadType.ReadAsDecimal, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsDoubleAsync(cancellationToken); } return DoReadAsDoubleAsync(cancellationToken); } internal async Task DoReadAsDoubleAsync(CancellationToken cancellationToken) { return (double?)(await ReadNumberValueAsync(ReadType.ReadAsDouble, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsInt32Async(cancellationToken); } return DoReadAsInt32Async(cancellationToken); } internal async Task DoReadAsInt32Async(CancellationToken cancellationToken) { return (int?)(await ReadNumberValueAsync(ReadType.ReadAsInt32, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public override Task ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.ReadAsStringAsync(cancellationToken); } return DoReadAsStringAsync(cancellationToken); } internal async Task DoReadAsStringAsync(CancellationToken cancellationToken) { return (string)(await ReadStringValueAsync(ReadType.ReadAsString, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } public JsonTextReader(TextReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } _reader = reader; _lineNumber = 1; _safeAsync = GetType() == typeof(JsonTextReader); } private void EnsureBufferNotEmpty() { if (_stringBuffer.IsEmpty) { _stringBuffer = new StringBuffer(_arrayPool, 1024); } } private void SetNewLine(bool hasNextChar) { if (hasNextChar && _chars[_charPos] == '\n') { _charPos++; } OnNewLine(_charPos); } private void OnNewLine(int pos) { _lineNumber++; _lineStartPos = pos; } private void ParseString(char quote, ReadType readType) { _charPos++; ShiftBufferIfNeeded(); ReadStringIntoBuffer(quote); ParseReadString(quote, readType); } private void ParseReadString(char quote, ReadType readType) { SetPostValueState(updateIndex: true); switch (readType) { case ReadType.ReadAsBytes: { Guid g; byte[] value2 = ((_stringReference.Length == 0) ? CollectionUtils.ArrayEmpty() : ((_stringReference.Length != 36 || !ConvertUtils.TryConvertGuid(_stringReference.ToString(), out g)) ? Convert.FromBase64CharArray(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length) : g.ToByteArray())); SetToken(JsonToken.Bytes, value2, updateIndex: false); return; } case ReadType.ReadAsString: { string value = _stringReference.ToString(); SetToken(JsonToken.String, value, updateIndex: false); _quoteChar = quote; return; } case ReadType.ReadAsInt32: case ReadType.ReadAsDecimal: case ReadType.ReadAsBoolean: return; } if (_dateParseHandling != 0) { DateTimeOffset dt2; if (readType switch { ReadType.ReadAsDateTime => 1, ReadType.ReadAsDateTimeOffset => 2, _ => (int)_dateParseHandling, } == 1) { if (DateTimeUtils.TryParseDateTime(_stringReference, base.DateTimeZoneHandling, base.DateFormatString, base.Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return; } } else if (DateTimeUtils.TryParseDateTimeOffset(_stringReference, base.DateFormatString, base.Culture, out dt2)) { SetToken(JsonToken.Date, dt2, updateIndex: false); return; } } SetToken(JsonToken.String, _stringReference.ToString(), updateIndex: false); _quoteChar = quote; } private static void BlockCopyChars(char[] src, int srcOffset, char[] dst, int dstOffset, int count) { Buffer.BlockCopy(src, srcOffset * 2, dst, dstOffset * 2, count * 2); } private void ShiftBufferIfNeeded() { int num = _chars.Length; if ((double)(num - _charPos) <= (double)num * 0.1 || num >= 1073741823) { int num2 = _charsUsed - _charPos; if (num2 > 0) { BlockCopyChars(_chars, _charPos, _chars, 0, num2); } _lineStartPos -= _charPos; _charPos = 0; _charsUsed = num2; _chars[_charsUsed] = '\0'; } } private int ReadData(bool append) { return ReadData(append, 0); } private void PrepareBufferForReadData(bool append, int charsRequired) { if (_charsUsed + charsRequired < _chars.Length - 1) { return; } if (append) { int num = _chars.Length * 2; int minSize = Math.Max((num < 0) ? int.MaxValue : num, _charsUsed + charsRequired + 1); char[] array = BufferUtils.RentBuffer(_arrayPool, minSize); BlockCopyChars(_chars, 0, array, 0, _chars.Length); BufferUtils.ReturnBuffer(_arrayPool, _chars); _chars = array; return; } int num2 = _charsUsed - _charPos; if (num2 + charsRequired + 1 >= _chars.Length) { char[] array2 = BufferUtils.RentBuffer(_arrayPool, num2 + charsRequired + 1); if (num2 > 0) { BlockCopyChars(_chars, _charPos, array2, 0, num2); } BufferUtils.ReturnBuffer(_arrayPool, _chars); _chars = array2; } else if (num2 > 0) { BlockCopyChars(_chars, _charPos, _chars, 0, num2); } _lineStartPos -= _charPos; _charPos = 0; _charsUsed = num2; } private int ReadData(bool append, int charsRequired) { if (_isEndOfFile) { return 0; } PrepareBufferForReadData(append, charsRequired); int count = _chars.Length - _charsUsed - 1; int num = _reader.Read(_chars, _charsUsed, count); _charsUsed += num; if (num == 0) { _isEndOfFile = true; } _chars[_charsUsed] = '\0'; return num; } private bool EnsureChars(int relativePosition, bool append) { if (_charPos + relativePosition >= _charsUsed) { return ReadChars(relativePosition, append); } return true; } private bool ReadChars(int relativePosition, bool append) { if (_isEndOfFile) { return false; } int num = _charPos + relativePosition - _charsUsed + 1; int num2 = 0; do { int num3 = ReadData(append, num - num2); if (num3 == 0) { break; } num2 += num3; } while (num2 < num); if (num2 < num) { return false; } return true; } public override bool Read() { EnsureBuffer(); do { switch (_currentState) { case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: return ParseValue(); case State.ObjectStart: case State.Object: return ParseObject(); case State.PostValue: break; case State.Finished: if (EnsureChars(0, append: false)) { EatWhitespace(); if (_isEndOfFile) { SetToken(JsonToken.None); return false; } if (_chars[_charPos] == '/') { ParseComment(setToken: true); return true; } throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } SetToken(JsonToken.None); return false; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } while (!ParsePostValue(ignoreComments: false)); return true; } public override int? ReadAsInt32() { return (int?)ReadNumberValue(ReadType.ReadAsInt32); } public override DateTime? ReadAsDateTime() { return (DateTime?)ReadStringValue(ReadType.ReadAsDateTime); } public override string? ReadAsString() { return (string)ReadStringValue(ReadType.ReadAsString); } public override byte[]? ReadAsBytes() { EnsureBuffer(); bool flag = false; switch (_currentState) { case State.PostValue: if (ParsePostValue(ignoreComments: true)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (ReadNullChar()) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': { ParseString(c, ReadType.ReadAsBytes); byte[] array = (byte[])Value; if (flag) { ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array, updateIndex: false); } return array; } case '{': _charPos++; SetToken(JsonToken.StartObject); ReadIntoWrappedTypeObject(); flag = true; break; case '[': _charPos++; SetToken(JsonToken.StartArray); return ReadArrayIntoByteArray(); case 'n': HandleNull(); return null; case '/': ParseComment(setToken: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: ReadFinished(); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private object? ReadStringValue(ReadType readType) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (ParsePostValue(ignoreComments: true)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (ReadNullChar()) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': ParseString(c, readType); return FinishReadQuotedStringValue(readType); case '-': if (EnsureChars(1, append: true) && _chars[_charPos + 1] == 'I') { return ParseNumberNegativeInfinity(readType); } ParseNumber(readType); return Value; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (readType != ReadType.ReadAsString) { _charPos++; throw CreateUnexpectedCharacterException(c); } ParseNumber(ReadType.ReadAsString); return Value; case 'f': case 't': { if (readType != ReadType.ReadAsString) { _charPos++; throw CreateUnexpectedCharacterException(c); } string text = ((c == 't') ? JsonConvert.True : JsonConvert.False); if (!MatchValueWithTrailingSeparator(text)) { throw CreateUnexpectedCharacterException(_chars[_charPos]); } SetToken(JsonToken.String, text); return text; } case 'I': return ParseNumberPositiveInfinity(readType); case 'N': return ParseNumberNaN(readType); case 'n': HandleNull(); return null; case '/': ParseComment(setToken: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: ReadFinished(); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private object? FinishReadQuotedStringValue(ReadType readType) { switch (readType) { case ReadType.ReadAsBytes: case ReadType.ReadAsString: return Value; case ReadType.ReadAsDateTime: if (Value is DateTime dateTime) { return dateTime; } return ReadDateTimeString((string)Value); case ReadType.ReadAsDateTimeOffset: if (Value is DateTimeOffset dateTimeOffset) { return dateTimeOffset; } return ReadDateTimeOffsetString((string)Value); default: throw new ArgumentOutOfRangeException("readType"); } } private JsonReaderException CreateUnexpectedCharacterException(char c) { return JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } public override bool? ReadAsBoolean() { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (ParsePostValue(ignoreComments: true)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (ReadNullChar()) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': ParseString(c, ReadType.Read); return ReadBooleanString(_stringReference.ToString()); case 'n': HandleNull(); return null; case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { ParseNumber(ReadType.Read); bool flag2 = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag2, updateIndex: false); return flag2; } case 'f': case 't': { bool flag = c == 't'; string value = (flag ? JsonConvert.True : JsonConvert.False); if (!MatchValueWithTrailingSeparator(value)) { throw CreateUnexpectedCharacterException(_chars[_charPos]); } SetToken(JsonToken.Boolean, BoxedPrimitives.Get(flag)); return flag; } case '/': ParseComment(setToken: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: ReadFinished(); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private void ProcessValueComma() { _charPos++; if (_currentState != State.PostValue) { SetToken(JsonToken.Undefined); JsonReaderException ex = CreateUnexpectedCharacterException(','); _charPos--; throw ex; } SetStateBasedOnCurrent(); } private object? ReadNumberValue(ReadType readType) { EnsureBuffer(); switch (_currentState) { case State.PostValue: if (ParsePostValue(ignoreComments: true)) { return null; } goto case State.Start; case State.Start: case State.Property: case State.ArrayStart: case State.Array: case State.ConstructorStart: case State.Constructor: while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (ReadNullChar()) { SetToken(JsonToken.None, null, updateIndex: false); return null; } break; case '"': case '\'': ParseString(c, readType); return FinishReadQuotedNumber(readType); case 'n': HandleNull(); return null; case 'N': return ParseNumberNaN(readType); case 'I': return ParseNumberPositiveInfinity(readType); case '-': if (EnsureChars(1, append: true) && _chars[_charPos + 1] == 'I') { return ParseNumberNegativeInfinity(readType); } ParseNumber(readType); return Value; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ParseNumber(readType); return Value; case '/': ParseComment(setToken: false); break; case ',': ProcessValueComma(); break; case ']': _charPos++; if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.PostValue) { SetToken(JsonToken.EndArray); return null; } throw CreateUnexpectedCharacterException(c); case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: _charPos++; if (!char.IsWhiteSpace(c)) { throw CreateUnexpectedCharacterException(c); } break; } } case State.Finished: ReadFinished(); return null; default: throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, base.CurrentState)); } } private object? FinishReadQuotedNumber(ReadType readType) { return readType switch { ReadType.ReadAsInt32 => ReadInt32String(_stringReference.ToString()), ReadType.ReadAsDecimal => ReadDecimalString(_stringReference.ToString()), ReadType.ReadAsDouble => ReadDoubleString(_stringReference.ToString()), _ => throw new ArgumentOutOfRangeException("readType"), }; } public override DateTimeOffset? ReadAsDateTimeOffset() { return (DateTimeOffset?)ReadStringValue(ReadType.ReadAsDateTimeOffset); } public override decimal? ReadAsDecimal() { return (decimal?)ReadNumberValue(ReadType.ReadAsDecimal); } public override double? ReadAsDouble() { return (double?)ReadNumberValue(ReadType.ReadAsDouble); } private void HandleNull() { if (EnsureChars(1, append: true)) { if (_chars[_charPos + 1] == 'u') { ParseNull(); return; } _charPos += 2; throw CreateUnexpectedCharacterException(_chars[_charPos - 1]); } _charPos = _charsUsed; throw CreateUnexpectedEndException(); } private void ReadFinished() { if (EnsureChars(0, append: false)) { EatWhitespace(); if (_isEndOfFile) { return; } if (_chars[_charPos] != '/') { throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } ParseComment(setToken: false); } SetToken(JsonToken.None); } private bool ReadNullChar() { if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { _isEndOfFile = true; return true; } } else { _charPos++; } return false; } private void EnsureBuffer() { if (_chars == null) { _chars = BufferUtils.RentBuffer(_arrayPool, 1024); _chars[0] = '\0'; } } private void ReadStringIntoBuffer(char quote) { int num = _charPos; int charPos = _charPos; int lastWritePosition = _charPos; _stringBuffer.Position = 0; while (true) { switch (_chars[num++]) { case '\0': if (_charsUsed == num - 1) { num--; if (ReadData(append: true) == 0) { _charPos = num; throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } } break; case '\\': { _charPos = num; if (!EnsureChars(0, append: true)) { throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote)); } int writeToPosition = num - 1; char c = _chars[num]; num++; char c2; switch (c) { case 'b': c2 = '\b'; break; case 't': c2 = '\t'; break; case 'n': c2 = '\n'; break; case 'f': c2 = '\f'; break; case 'r': c2 = '\r'; break; case '\\': c2 = '\\'; break; case '"': case '\'': case '/': c2 = c; break; case 'u': _charPos = num; c2 = ParseUnicode(); if (StringUtils.IsLowSurrogate(c2)) { c2 = '\ufffd'; } else if (StringUtils.IsHighSurrogate(c2)) { bool flag; do { flag = false; if (EnsureChars(2, append: true) && _chars[_charPos] == '\\' && _chars[_charPos + 1] == 'u') { char writeChar = c2; _charPos += 2; c2 = ParseUnicode(); if (!StringUtils.IsLowSurrogate(c2)) { if (StringUtils.IsHighSurrogate(c2)) { writeChar = '\ufffd'; flag = true; } else { writeChar = '\ufffd'; } } EnsureBufferNotEmpty(); WriteCharToBuffer(writeChar, lastWritePosition, writeToPosition); lastWritePosition = _charPos; } else { c2 = '\ufffd'; } } while (flag); } num = _charPos; break; default: _charPos = num; throw JsonReaderException.Create(this, "Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, "\\" + c)); } EnsureBufferNotEmpty(); WriteCharToBuffer(c2, lastWritePosition, writeToPosition); lastWritePosition = num; break; } case '\r': _charPos = num - 1; ProcessCarriageReturn(append: true); num = _charPos; break; case '\n': _charPos = num - 1; ProcessLineFeed(); num = _charPos; break; case '"': case '\'': if (_chars[num - 1] == quote) { FinishReadStringIntoBuffer(num - 1, charPos, lastWritePosition); return; } break; } } } private void FinishReadStringIntoBuffer(int charPos, int initialPosition, int lastWritePosition) { if (initialPosition == lastWritePosition) { _stringReference = new StringReference(_chars, initialPosition, charPos - initialPosition); } else { EnsureBufferNotEmpty(); if (charPos > lastWritePosition) { _stringBuffer.Append(_arrayPool, _chars, lastWritePosition, charPos - lastWritePosition); } _stringReference = new StringReference(_stringBuffer.InternalBuffer, 0, _stringBuffer.Position); } _charPos = charPos + 1; } private void WriteCharToBuffer(char writeChar, int lastWritePosition, int writeToPosition) { if (writeToPosition > lastWritePosition) { _stringBuffer.Append(_arrayPool, _chars, lastWritePosition, writeToPosition - lastWritePosition); } _stringBuffer.Append(_arrayPool, writeChar); } private char ConvertUnicode(bool enoughChars) { if (enoughChars) { if (ConvertUtils.TryHexTextToInt(_chars, _charPos, _charPos + 4, out var value)) { char result = Convert.ToChar(value); _charPos += 4; return result; } throw JsonReaderException.Create(this, "Invalid Unicode escape sequence: \\u{0}.".FormatWith(CultureInfo.InvariantCulture, new string(_chars, _charPos, 4))); } throw JsonReaderException.Create(this, "Unexpected end while parsing Unicode escape sequence."); } private char ParseUnicode() { return ConvertUnicode(EnsureChars(4, append: true)); } private void ReadNumberIntoBuffer() { int num = _charPos; while (true) { char c = _chars[num]; if (c == '\0') { _charPos = num; if (_charsUsed != num || ReadData(append: true) == 0) { break; } } else { if (ReadNumberCharIntoBuffer(c, num)) { break; } num++; } } } private bool ReadNumberCharIntoBuffer(char currentChar, int charPos) { switch (currentChar) { case '+': case '-': case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'X': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'x': return false; default: _charPos = charPos; if (char.IsWhiteSpace(currentChar) || currentChar == ',' || currentChar == '}' || currentChar == ']' || currentChar == ')' || currentChar == '/') { return true; } throw JsonReaderException.Create(this, "Unexpected character encountered while parsing number: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); } } private void ClearRecentString() { _stringBuffer.Position = 0; _stringReference = default(StringReference); } private bool ParsePostValue(bool ignoreComments) { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { _currentState = State.Finished; return false; } } else { _charPos++; } continue; case '}': _charPos++; SetToken(JsonToken.EndObject); return true; case ']': _charPos++; SetToken(JsonToken.EndArray); return true; case ')': _charPos++; SetToken(JsonToken.EndConstructor); return true; case '/': ParseComment(!ignoreComments); if (!ignoreComments) { return true; } continue; case ',': _charPos++; SetStateBasedOnCurrent(); return false; case '\t': case ' ': _charPos++; continue; case '\r': ProcessCarriageReturn(append: false); continue; case '\n': ProcessLineFeed(); continue; } if (char.IsWhiteSpace(c)) { _charPos++; continue; } if (base.SupportMultipleContent && Depth == 0) { SetStateBasedOnCurrent(); return false; } throw JsonReaderException.Create(this, "After parsing a value an unexpected character was encountered: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } } private bool ParseObject() { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { return false; } } else { _charPos++; } break; case '}': SetToken(JsonToken.EndObject); _charPos++; return true; case '/': ParseComment(setToken: true); return true; case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: if (char.IsWhiteSpace(c)) { _charPos++; break; } return ParseProperty(); } } } private bool ParseProperty() { char c = _chars[_charPos]; char c2; if (c == '"' || c == '\'') { _charPos++; c2 = c; ShiftBufferIfNeeded(); ReadStringIntoBuffer(c2); } else { if (!ValidIdentifierChar(c)) { throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } c2 = '\0'; ShiftBufferIfNeeded(); ParseUnquotedProperty(); } string text; if (PropertyNameTable != null) { text = PropertyNameTable.Get(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length); if (text == null) { text = _stringReference.ToString(); } } else { text = _stringReference.ToString(); } EatWhitespace(); if (_chars[_charPos] != ':') { throw JsonReaderException.Create(this, "Invalid character after parsing property name. Expected ':' but got: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } _charPos++; SetToken(JsonToken.PropertyName, text); _quoteChar = c2; ClearRecentString(); return true; } private bool ValidIdentifierChar(char value) { if (!char.IsLetterOrDigit(value) && value != '_') { return value == '$'; } return true; } private void ParseUnquotedProperty() { int charPos = _charPos; while (true) { char c = _chars[_charPos]; if (c == '\0') { if (_charsUsed != _charPos) { _stringReference = new StringReference(_chars, charPos, _charPos - charPos); break; } if (ReadData(append: true) == 0) { throw JsonReaderException.Create(this, "Unexpected end while parsing unquoted property name."); } } else if (ReadUnquotedPropertyReportIfDone(c, charPos)) { break; } } } private bool ReadUnquotedPropertyReportIfDone(char currentChar, int initialPosition) { if (ValidIdentifierChar(currentChar)) { _charPos++; return false; } if (char.IsWhiteSpace(currentChar) || currentChar == ':') { _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition); return true; } throw JsonReaderException.Create(this, "Invalid JavaScript property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar)); } private bool ParseValue() { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { return false; } } else { _charPos++; } break; case '"': case '\'': ParseString(c, ReadType.Read); return true; case 't': ParseTrue(); return true; case 'f': ParseFalse(); return true; case 'n': if (EnsureChars(1, append: true)) { switch (_chars[_charPos + 1]) { case 'u': ParseNull(); break; case 'e': ParseConstructor(); break; default: throw CreateUnexpectedCharacterException(_chars[_charPos]); } return true; } _charPos++; throw CreateUnexpectedEndException(); case 'N': ParseNumberNaN(ReadType.Read); return true; case 'I': ParseNumberPositiveInfinity(ReadType.Read); return true; case '-': if (EnsureChars(1, append: true) && _chars[_charPos + 1] == 'I') { ParseNumberNegativeInfinity(ReadType.Read); } else { ParseNumber(ReadType.Read); } return true; case '/': ParseComment(setToken: true); return true; case 'u': ParseUndefined(); return true; case '{': _charPos++; SetToken(JsonToken.StartObject); return true; case '[': _charPos++; SetToken(JsonToken.StartArray); return true; case ']': _charPos++; SetToken(JsonToken.EndArray); return true; case ',': SetToken(JsonToken.Undefined); return true; case ')': _charPos++; SetToken(JsonToken.EndConstructor); return true; case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; case '\t': case ' ': _charPos++; break; default: if (char.IsWhiteSpace(c)) { _charPos++; break; } if (char.IsNumber(c) || c == '-' || c == '.') { ParseNumber(ReadType.Read); return true; } throw CreateUnexpectedCharacterException(c); } } } private void ProcessLineFeed() { _charPos++; OnNewLine(_charPos); } private void ProcessCarriageReturn(bool append) { _charPos++; SetNewLine(EnsureChars(1, append)); } private void EatWhitespace() { while (true) { char c = _chars[_charPos]; switch (c) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: false) == 0) { return; } } else { _charPos++; } break; case '\r': ProcessCarriageReturn(append: false); break; case '\n': ProcessLineFeed(); break; default: if (!char.IsWhiteSpace(c)) { return; } goto case ' '; case ' ': _charPos++; break; } } } private void ParseConstructor() { if (MatchValueWithTrailingSeparator("new")) { EatWhitespace(); int charPos = _charPos; int charPos2; while (true) { char c = _chars[_charPos]; if (c == '\0') { if (_charsUsed == _charPos) { if (ReadData(append: true) == 0) { throw JsonReaderException.Create(this, "Unexpected end while parsing constructor."); } continue; } charPos2 = _charPos; _charPos++; break; } if (char.IsLetterOrDigit(c)) { _charPos++; continue; } switch (c) { case '\r': charPos2 = _charPos; ProcessCarriageReturn(append: true); break; case '\n': charPos2 = _charPos; ProcessLineFeed(); break; default: if (char.IsWhiteSpace(c)) { charPos2 = _charPos; _charPos++; break; } if (c == '(') { charPos2 = _charPos; break; } throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, c)); } break; } _stringReference = new StringReference(_chars, charPos, charPos2 - charPos); string value = _stringReference.ToString(); EatWhitespace(); if (_chars[_charPos] != '(') { throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } _charPos++; ClearRecentString(); SetToken(JsonToken.StartConstructor, value); return; } throw JsonReaderException.Create(this, "Unexpected content while parsing JSON."); } private void ParseNumber(ReadType readType) { ShiftBufferIfNeeded(); char firstChar = _chars[_charPos]; int charPos = _charPos; ReadNumberIntoBuffer(); ParseReadNumber(readType, firstChar, charPos); } private void ParseReadNumber(ReadType readType, char firstChar, int initialPosition) { SetPostValueState(updateIndex: true); _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition); bool flag = char.IsDigit(firstChar) && _stringReference.Length == 1; bool flag2 = firstChar == '0' && _stringReference.Length > 1 && _stringReference.Chars[_stringReference.StartIndex + 1] != '.' && _stringReference.Chars[_stringReference.StartIndex + 1] != 'e' && _stringReference.Chars[_stringReference.StartIndex + 1] != 'E'; JsonToken newToken; object value; switch (readType) { case ReadType.ReadAsString: { string text5 = _stringReference.ToString(); double result3; if (flag2) { try { if (text5.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { Convert.ToInt64(text5, 16); } else { Convert.ToInt64(text5, 8); } } catch (Exception ex4) { throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, text5), ex4); } } else if (!double.TryParse(text5, NumberStyles.Float, CultureInfo.InvariantCulture, out result3)) { throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } newToken = JsonToken.String; value = text5; break; } case ReadType.ReadAsInt32: if (flag) { value = BoxedPrimitives.Get(firstChar - 48); } else if (flag2) { string text6 = _stringReference.ToString(); try { value = BoxedPrimitives.Get(text6.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt32(text6, 16) : Convert.ToInt32(text6, 8)); } catch (Exception ex5) { throw ThrowReaderError("Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, text6), ex5); } } else { int value5; switch (ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value5)) { case ParseResult.Success: break; case ParseResult.Overflow: throw ThrowReaderError("JSON integer {0} is too large or small for an Int32.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); default: throw ThrowReaderError("Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(value5); } newToken = JsonToken.Integer; break; case ReadType.ReadAsDecimal: if (flag) { value = BoxedPrimitives.Get((decimal)firstChar - 48m); } else if (flag2) { string text3 = _stringReference.ToString(); try { value = BoxedPrimitives.Get(Convert.ToDecimal(text3.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(text3, 16) : Convert.ToInt64(text3, 8))); } catch (Exception ex2) { throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, text3), ex2); } } else { if (ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out var value4) != ParseResult.Success) { throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(value4); } newToken = JsonToken.Float; break; case ReadType.ReadAsDouble: if (flag) { value = BoxedPrimitives.Get((double)(int)firstChar - 48.0); } else if (flag2) { string text4 = _stringReference.ToString(); try { value = BoxedPrimitives.Get(Convert.ToDouble(text4.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(text4, 16) : Convert.ToInt64(text4, 8))); } catch (Exception ex3) { throw ThrowReaderError("Input string '{0}' is not a valid double.".FormatWith(CultureInfo.InvariantCulture, text4), ex3); } } else { if (!double.TryParse(_stringReference.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result2)) { throw ThrowReaderError("Input string '{0}' is not a valid double.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(result2); } newToken = JsonToken.Float; break; case ReadType.Read: case ReadType.ReadAsInt64: { if (flag) { value = BoxedPrimitives.Get((long)firstChar - 48L); newToken = JsonToken.Integer; break; } if (flag2) { string text = _stringReference.ToString(); try { value = BoxedPrimitives.Get(text.StartsWith("0x", StringComparison.OrdinalIgnoreCase) ? Convert.ToInt64(text, 16) : Convert.ToInt64(text, 8)); } catch (Exception ex) { throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, text), ex); } newToken = JsonToken.Integer; break; } long value2; switch (ConvertUtils.Int64TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value2)) { case ParseResult.Success: value = BoxedPrimitives.Get(value2); newToken = JsonToken.Integer; break; case ParseResult.Overflow: { string text2 = _stringReference.ToString(); if (text2.Length > 380) { throw ThrowReaderError("JSON integer {0} is too large to parse.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BigIntegerParse(text2, CultureInfo.InvariantCulture); newToken = JsonToken.Integer; break; } default: if (_floatParseHandling == FloatParseHandling.Decimal) { decimal value3; ParseResult parseResult = ConvertUtils.DecimalTryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value3); if (parseResult != ParseResult.Success) { throw ThrowReaderError("Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(value3); } else { if (!double.TryParse(_stringReference.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw ThrowReaderError("Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString())); } value = BoxedPrimitives.Get(result); } newToken = JsonToken.Float; break; } break; } default: throw JsonReaderException.Create(this, "Cannot read number value as type."); } ClearRecentString(); SetToken(newToken, value, updateIndex: false); } private JsonReaderException ThrowReaderError(string message, Exception? ex = null) { SetToken(JsonToken.Undefined, null, updateIndex: false); return JsonReaderException.Create(this, message, ex); } [MethodImpl(MethodImplOptions.NoInlining)] private static object BigIntegerParse(string number, CultureInfo culture) { return BigInteger.Parse(number, culture); } private void ParseComment(bool setToken) { _charPos++; if (!EnsureChars(1, append: false)) { throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); } bool flag; if (_chars[_charPos] == '*') { flag = false; } else { if (_chars[_charPos] != '/') { throw JsonReaderException.Create(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos])); } flag = true; } _charPos++; int charPos = _charPos; while (true) { switch (_chars[_charPos]) { case '\0': if (_charsUsed == _charPos) { if (ReadData(append: true) == 0) { if (!flag) { throw JsonReaderException.Create(this, "Unexpected end while parsing comment."); } EndComment(setToken, charPos, _charPos); return; } } else { _charPos++; } break; case '*': _charPos++; if (!flag && EnsureChars(0, append: true) && _chars[_charPos] == '/') { EndComment(setToken, charPos, _charPos - 1); _charPos++; return; } break; case '\r': if (flag) { EndComment(setToken, charPos, _charPos); return; } ProcessCarriageReturn(append: true); break; case '\n': if (flag) { EndComment(setToken, charPos, _charPos); return; } ProcessLineFeed(); break; default: _charPos++; break; } } } private void EndComment(bool setToken, int initialPosition, int endPosition) { if (setToken) { SetToken(JsonToken.Comment, new string(_chars, initialPosition, endPosition - initialPosition)); } } private bool MatchValue(string value) { return MatchValue(EnsureChars(value.Length - 1, append: true), value); } private bool MatchValue(bool enoughChars, string value) { if (!enoughChars) { _charPos = _charsUsed; throw CreateUnexpectedEndException(); } for (int i = 0; i < value.Length; i++) { if (_chars[_charPos + i] != value[i]) { _charPos += i; return false; } } _charPos += value.Length; return true; } private bool MatchValueWithTrailingSeparator(string value) { if (!MatchValue(value)) { return false; } if (!EnsureChars(0, append: false)) { return true; } if (!IsSeparator(_chars[_charPos])) { return _chars[_charPos] == '\0'; } return true; } private bool IsSeparator(char c) { switch (c) { case ',': case ']': case '}': return true; case '/': { if (!EnsureChars(1, append: false)) { return false; } char c2 = _chars[_charPos + 1]; if (c2 != '*') { return c2 == '/'; } return true; } case ')': if (base.CurrentState == State.Constructor || base.CurrentState == State.ConstructorStart) { return true; } break; case '\t': case '\n': case '\r': case ' ': return true; default: if (char.IsWhiteSpace(c)) { return true; } break; } return false; } private void ParseTrue() { if (MatchValueWithTrailingSeparator(JsonConvert.True)) { SetToken(JsonToken.Boolean, BoxedPrimitives.BooleanTrue); return; } throw JsonReaderException.Create(this, "Error parsing boolean value."); } private void ParseNull() { if (MatchValueWithTrailingSeparator(JsonConvert.Null)) { SetToken(JsonToken.Null); return; } throw JsonReaderException.Create(this, "Error parsing null value."); } private void ParseUndefined() { if (MatchValueWithTrailingSeparator(JsonConvert.Undefined)) { SetToken(JsonToken.Undefined); return; } throw JsonReaderException.Create(this, "Error parsing undefined value."); } private void ParseFalse() { if (MatchValueWithTrailingSeparator(JsonConvert.False)) { SetToken(JsonToken.Boolean, BoxedPrimitives.BooleanFalse); return; } throw JsonReaderException.Create(this, "Error parsing boolean value."); } private object ParseNumberNegativeInfinity(ReadType readType) { return ParseNumberNegativeInfinity(readType, MatchValueWithTrailingSeparator(JsonConvert.NegativeInfinity)); } private object ParseNumberNegativeInfinity(ReadType readType, bool matched) { if (matched) { switch (readType) { case ReadType.Read: case ReadType.ReadAsDouble: if (_floatParseHandling == FloatParseHandling.Double) { SetToken(JsonToken.Float, BoxedPrimitives.DoubleNegativeInfinity); return double.NegativeInfinity; } break; case ReadType.ReadAsString: SetToken(JsonToken.String, JsonConvert.NegativeInfinity); return JsonConvert.NegativeInfinity; } throw JsonReaderException.Create(this, "Cannot read -Infinity value."); } throw JsonReaderException.Create(this, "Error parsing -Infinity value."); } private object ParseNumberPositiveInfinity(ReadType readType) { return ParseNumberPositiveInfinity(readType, MatchValueWithTrailingSeparator(JsonConvert.PositiveInfinity)); } private object ParseNumberPositiveInfinity(ReadType readType, bool matched) { if (matched) { switch (readType) { case ReadType.Read: case ReadType.ReadAsDouble: if (_floatParseHandling == FloatParseHandling.Double) { SetToken(JsonToken.Float, BoxedPrimitives.DoublePositiveInfinity); return double.PositiveInfinity; } break; case ReadType.ReadAsString: SetToken(JsonToken.String, JsonConvert.PositiveInfinity); return JsonConvert.PositiveInfinity; } throw JsonReaderException.Create(this, "Cannot read Infinity value."); } throw JsonReaderException.Create(this, "Error parsing Infinity value."); } private object ParseNumberNaN(ReadType readType) { return ParseNumberNaN(readType, MatchValueWithTrailingSeparator(JsonConvert.NaN)); } private object ParseNumberNaN(ReadType readType, bool matched) { if (matched) { switch (readType) { case ReadType.Read: case ReadType.ReadAsDouble: if (_floatParseHandling == FloatParseHandling.Double) { SetToken(JsonToken.Float, BoxedPrimitives.DoubleNaN); return double.NaN; } break; case ReadType.ReadAsString: SetToken(JsonToken.String, JsonConvert.NaN); return JsonConvert.NaN; } throw JsonReaderException.Create(this, "Cannot read NaN value."); } throw JsonReaderException.Create(this, "Error parsing NaN value."); } public override void Close() { base.Close(); if (_chars != null) { BufferUtils.ReturnBuffer(_arrayPool, _chars); _chars = null; } if (base.CloseInput) { _reader?.Close(); } _stringBuffer.Clear(_arrayPool); } public bool HasLineInfo() { return true; } } internal enum ReadType { Read, ReadAsInt32, ReadAsInt64, ReadAsBytes, ReadAsString, ReadAsDecimal, ReadAsDateTime, ReadAsDateTimeOffset, ReadAsDouble, ReadAsBoolean } internal class JsonTextWriter : JsonWriter { private readonly bool _safeAsync; private const int IndentCharBufferSize = 12; private readonly TextWriter _writer; private Base64Encoder? _base64Encoder; private char _indentChar; private int _indentation; private char _quoteChar; private bool _quoteName; private bool[]? _charEscapeFlags; private char[]? _writeBuffer; private IArrayPool? _arrayPool; private char[]? _indentChars; private Base64Encoder Base64Encoder { get { if (_base64Encoder == null) { _base64Encoder = new Base64Encoder(_writer); } return _base64Encoder; } } public IArrayPool? ArrayPool { get { return _arrayPool; } set { if (value == null) { throw new ArgumentNullException("value"); } _arrayPool = value; } } public int Indentation { get { return _indentation; } set { if (value < 0) { throw new ArgumentException("Indentation value must be greater than 0."); } _indentation = value; } } public char QuoteChar { get { return _quoteChar; } set { if (value != '"' && value != '\'') { throw new ArgumentException("Invalid JavaScript string quote character. Valid quote characters are ' and \"."); } _quoteChar = value; UpdateCharEscapeFlags(); } } public char IndentChar { get { return _indentChar; } set { if (value != _indentChar) { _indentChar = value; _indentChars = null; } } } public bool QuoteName { get { return _quoteName; } set { _quoteName = value; } } public override Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.FlushAsync(cancellationToken); } return DoFlushAsync(cancellationToken); } internal Task DoFlushAsync(CancellationToken cancellationToken) { return cancellationToken.CancelIfRequestedAsync() ?? _writer.FlushAsync(); } protected override Task WriteValueDelimiterAsync(CancellationToken cancellationToken) { if (!_safeAsync) { return base.WriteValueDelimiterAsync(cancellationToken); } return DoWriteValueDelimiterAsync(cancellationToken); } internal Task DoWriteValueDelimiterAsync(CancellationToken cancellationToken) { return _writer.WriteAsync(',', cancellationToken); } protected override Task WriteEndAsync(JsonToken token, CancellationToken cancellationToken) { if (!_safeAsync) { return base.WriteEndAsync(token, cancellationToken); } return DoWriteEndAsync(token, cancellationToken); } internal Task DoWriteEndAsync(JsonToken token, CancellationToken cancellationToken) { return token switch { JsonToken.EndObject => _writer.WriteAsync('}', cancellationToken), JsonToken.EndArray => _writer.WriteAsync(']', cancellationToken), JsonToken.EndConstructor => _writer.WriteAsync(')', cancellationToken), _ => throw JsonWriterException.Create(this, "Invalid JsonToken: " + token, null), }; } public override Task CloseAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.CloseAsync(cancellationToken); } return DoCloseAsync(cancellationToken); } internal async Task DoCloseAsync(CancellationToken cancellationToken) { if (base.Top == 0) { cancellationToken.ThrowIfCancellationRequested(); } while (base.Top > 0) { await WriteEndAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await CloseBufferAndWriterAsync().ConfigureAwait(continueOnCapturedContext: false); } private async Task CloseBufferAndWriterAsync() { if (_writeBuffer != null) { BufferUtils.ReturnBuffer(_arrayPool, _writeBuffer); _writeBuffer = null; } if (base.CloseOutput && _writer != null) { await _writer.FlushAsync().ConfigureAwait(continueOnCapturedContext: false); _writer.Close(); } } public override Task WriteEndAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteEndAsync(cancellationToken); } return WriteEndInternalAsync(cancellationToken); } protected override Task WriteIndentAsync(CancellationToken cancellationToken) { if (!_safeAsync) { return base.WriteIndentAsync(cancellationToken); } return DoWriteIndentAsync(cancellationToken); } internal Task DoWriteIndentAsync(CancellationToken cancellationToken) { int num = base.Top * _indentation; int num2 = SetIndentChars(); if (num <= 12) { return _writer.WriteAsync(_indentChars, 0, num2 + num, cancellationToken); } return WriteIndentAsync(num, num2, cancellationToken); } private async Task WriteIndentAsync(int currentIndentCount, int newLineLen, CancellationToken cancellationToken) { await _writer.WriteAsync(_indentChars, 0, newLineLen + Math.Min(currentIndentCount, 12), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); while (true) { int num; currentIndentCount = (num = currentIndentCount - 12); if (num <= 0) { break; } await _writer.WriteAsync(_indentChars, newLineLen, Math.Min(currentIndentCount, 12), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } private Task WriteValueInternalAsync(JsonToken token, string value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(token, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync(value, cancellationToken); } return WriteValueInternalAsync(task, value, cancellationToken); } private async Task WriteValueInternalAsync(Task task, string value, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } protected override Task WriteIndentSpaceAsync(CancellationToken cancellationToken) { if (!_safeAsync) { return base.WriteIndentSpaceAsync(cancellationToken); } return DoWriteIndentSpaceAsync(cancellationToken); } internal Task DoWriteIndentSpaceAsync(CancellationToken cancellationToken) { return _writer.WriteAsync(' ', cancellationToken); } public override Task WriteRawAsync(string? json, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteRawAsync(json, cancellationToken); } return DoWriteRawAsync(json, cancellationToken); } internal Task DoWriteRawAsync(string? json, CancellationToken cancellationToken) { return _writer.WriteAsync(json, cancellationToken); } public override Task WriteNullAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteNullAsync(cancellationToken); } return DoWriteNullAsync(cancellationToken); } internal Task DoWriteNullAsync(CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Null, JsonConvert.Null, cancellationToken); } private Task WriteDigitsAsync(ulong uvalue, bool negative, CancellationToken cancellationToken) { if (uvalue <= 9 && !negative) { return _writer.WriteAsync((char)(48 + uvalue), cancellationToken); } int count = WriteNumberToBuffer(uvalue, negative); return _writer.WriteAsync(_writeBuffer, 0, count, cancellationToken); } private Task WriteIntegerValueAsync(ulong uvalue, bool negative, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.Integer, cancellationToken); if (task.IsCompletedSuccessfully()) { return WriteDigitsAsync(uvalue, negative, cancellationToken); } return WriteIntegerValueAsync(task, uvalue, negative, cancellationToken); } private async Task WriteIntegerValueAsync(Task task, ulong uvalue, bool negative, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteDigitsAsync(uvalue, negative, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } internal Task WriteIntegerValueAsync(long value, CancellationToken cancellationToken) { bool flag = value < 0; if (flag) { value = -value; } return WriteIntegerValueAsync((ulong)value, flag, cancellationToken); } internal Task WriteIntegerValueAsync(ulong uvalue, CancellationToken cancellationToken) { return WriteIntegerValueAsync(uvalue, negative: false, cancellationToken); } private Task WriteEscapedStringAsync(string value, bool quote, CancellationToken cancellationToken) { return JavaScriptUtils.WriteEscapedJavaScriptStringAsync(_writer, value, _quoteChar, quote, _charEscapeFlags, base.StringEscapeHandling, this, _writeBuffer, cancellationToken); } public override Task WritePropertyNameAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WritePropertyNameAsync(name, cancellationToken); } return DoWritePropertyNameAsync(name, cancellationToken); } internal Task DoWritePropertyNameAsync(string name, CancellationToken cancellationToken) { Task task = InternalWritePropertyNameAsync(name, cancellationToken); if (!task.IsCompletedSuccessfully()) { return DoWritePropertyNameAsync(task, name, cancellationToken); } task = WriteEscapedStringAsync(name, _quoteName, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync(':', cancellationToken); } return JavaScriptUtils.WriteCharAsync(task, _writer, ':', cancellationToken); } private async Task DoWritePropertyNameAsync(Task task, string name, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteEscapedStringAsync(name, _quoteName, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(':').ConfigureAwait(continueOnCapturedContext: false); } public override Task WritePropertyNameAsync(string name, bool escape, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WritePropertyNameAsync(name, escape, cancellationToken); } return DoWritePropertyNameAsync(name, escape, cancellationToken); } internal async Task DoWritePropertyNameAsync(string name, bool escape, CancellationToken cancellationToken) { await InternalWritePropertyNameAsync(name, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (escape) { await WriteEscapedStringAsync(name, _quoteName, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { if (_quoteName) { await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } await _writer.WriteAsync(name, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (_quoteName) { await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } } await _writer.WriteAsync(':').ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteStartArrayAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteStartArrayAsync(cancellationToken); } return DoWriteStartArrayAsync(cancellationToken); } internal Task DoWriteStartArrayAsync(CancellationToken cancellationToken) { Task task = InternalWriteStartAsync(JsonToken.StartArray, JsonContainerType.Array, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync('[', cancellationToken); } return DoWriteStartArrayAsync(task, cancellationToken); } internal async Task DoWriteStartArrayAsync(Task task, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync('[', cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteStartObjectAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteStartObjectAsync(cancellationToken); } return DoWriteStartObjectAsync(cancellationToken); } internal Task DoWriteStartObjectAsync(CancellationToken cancellationToken) { Task task = InternalWriteStartAsync(JsonToken.StartObject, JsonContainerType.Object, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync('{', cancellationToken); } return DoWriteStartObjectAsync(task, cancellationToken); } internal async Task DoWriteStartObjectAsync(Task task, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync('{', cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteStartConstructorAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteStartConstructorAsync(name, cancellationToken); } return DoWriteStartConstructorAsync(name, cancellationToken); } internal async Task DoWriteStartConstructorAsync(string name, CancellationToken cancellationToken) { await InternalWriteStartAsync(JsonToken.StartConstructor, JsonContainerType.Constructor, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync("new ", cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(name, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync('(').ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteUndefinedAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteUndefinedAsync(cancellationToken); } return DoWriteUndefinedAsync(cancellationToken); } internal Task DoWriteUndefinedAsync(CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.Undefined, cancellationToken); if (task.IsCompletedSuccessfully()) { return _writer.WriteAsync(JsonConvert.Undefined, cancellationToken); } return DoWriteUndefinedAsync(task, cancellationToken); } private async Task DoWriteUndefinedAsync(Task task, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(JsonConvert.Undefined, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteWhitespaceAsync(string ws, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteWhitespaceAsync(ws, cancellationToken); } return DoWriteWhitespaceAsync(ws, cancellationToken); } internal Task DoWriteWhitespaceAsync(string ws, CancellationToken cancellationToken) { InternalWriteWhitespace(ws); return _writer.WriteAsync(ws, cancellationToken); } public override Task WriteValueAsync(bool value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(bool value, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Boolean, JsonConvert.ToString(value), cancellationToken); } public override Task WriteValueAsync(bool? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(bool? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(byte value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } public override Task WriteValueAsync(byte? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(byte? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } if (value != null) { return WriteValueNonNullAsync(value, cancellationToken); } return WriteNullAsync(cancellationToken); } internal async Task WriteValueNonNullAsync(byte[] value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.Bytes, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); await Base64Encoder.EncodeAsync(value, 0, value.Length, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await Base64Encoder.FlushAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteValueAsync(char value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(char value, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.String, JsonConvert.ToString(value), cancellationToken); } public override Task WriteValueAsync(char? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(char? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(DateTime value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal async Task DoWriteValueAsync(DateTime value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); value = DateTimeUtils.EnsureDateTime(value, base.DateTimeZoneHandling); if (StringUtils.IsNullOrEmpty(base.DateFormatString)) { int count = WriteValueToBuffer(value); await _writer.WriteAsync(_writeBuffer, 0, count, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value.ToString(base.DateFormatString, base.Culture), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } } public override Task WriteValueAsync(DateTime? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(DateTime? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal async Task DoWriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.Date, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (StringUtils.IsNullOrEmpty(base.DateFormatString)) { int count = WriteValueToBuffer(value); await _writer.WriteAsync(_writeBuffer, 0, count, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value.ToString(base.DateFormatString, base.Culture), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } } public override Task WriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(decimal value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(decimal value, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Float, JsonConvert.ToString(value), cancellationToken); } public override Task WriteValueAsync(decimal? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(decimal? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(double value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteValueAsync(value, nullable: false, cancellationToken); } internal Task WriteValueAsync(double value, bool nullable, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Float, JsonConvert.ToString(value, base.FloatFormatHandling, QuoteChar, nullable), cancellationToken); } public override Task WriteValueAsync(double? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } if (!value.HasValue) { return WriteNullAsync(cancellationToken); } return WriteValueAsync(value.GetValueOrDefault(), nullable: true, cancellationToken); } public override Task WriteValueAsync(float value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteValueAsync(value, nullable: false, cancellationToken); } internal Task WriteValueAsync(float value, bool nullable, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Float, JsonConvert.ToString(value, base.FloatFormatHandling, QuoteChar, nullable), cancellationToken); } public override Task WriteValueAsync(float? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } if (!value.HasValue) { return WriteNullAsync(cancellationToken); } return WriteValueAsync(value.GetValueOrDefault(), nullable: true, cancellationToken); } public override Task WriteValueAsync(Guid value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal async Task DoWriteValueAsync(Guid value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.String, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value.ToString("D", CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteValueAsync(Guid? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(Guid? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(int value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } public override Task WriteValueAsync(int? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(int? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(long value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } public override Task WriteValueAsync(long? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(long? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } internal Task WriteValueAsync(BigInteger value, CancellationToken cancellationToken) { return WriteValueInternalAsync(JsonToken.Integer, value.ToString(CultureInfo.InvariantCulture), cancellationToken); } public override Task WriteValueAsync(object? value, CancellationToken cancellationToken = default(CancellationToken)) { if (_safeAsync) { if (value == null) { return WriteNullAsync(cancellationToken); } if (value is BigInteger value2) { return WriteValueAsync(value2, cancellationToken); } return JsonWriter.WriteValueAsync(this, ConvertUtils.GetTypeCode(value.GetType()), value, cancellationToken); } return base.WriteValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(sbyte value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(sbyte? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(sbyte? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(short value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } public override Task WriteValueAsync(short? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(short? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(string? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(string? value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); if (task.IsCompletedSuccessfully()) { if (value != null) { return WriteEscapedStringAsync(value, quote: true, cancellationToken); } return _writer.WriteAsync(JsonConvert.Null, cancellationToken); } return DoWriteValueAsync(task, value, cancellationToken); } private async Task DoWriteValueAsync(Task task, string? value, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await ((value == null) ? _writer.WriteAsync(JsonConvert.Null, cancellationToken) : WriteEscapedStringAsync(value, quote: true, cancellationToken)).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteValueAsync(TimeSpan value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal async Task DoWriteValueAsync(TimeSpan value, CancellationToken cancellationToken) { await InternalWriteValueAsync(JsonToken.String, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(value.ToString(null, CultureInfo.InvariantCulture), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(_quoteChar, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteValueAsync(TimeSpan? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(TimeSpan? value, CancellationToken cancellationToken) { if (value.HasValue) { return DoWriteValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(uint value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(uint? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(uint? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(ulong value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(ulong? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(ulong? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } if (!(value == null)) { return WriteValueNotNullAsync(value, cancellationToken); } return WriteNullAsync(cancellationToken); } internal Task WriteValueNotNullAsync(Uri value, CancellationToken cancellationToken) { Task task = InternalWriteValueAsync(JsonToken.String, cancellationToken); if (task.IsCompletedSuccessfully()) { return WriteEscapedStringAsync(value.OriginalString, quote: true, cancellationToken); } return WriteValueNotNullAsync(task, value, cancellationToken); } internal async Task WriteValueNotNullAsync(Task task, Uri value, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteEscapedStringAsync(value.OriginalString, quote: true, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } [CLSCompliant(false)] public override Task WriteValueAsync(ushort value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return WriteIntegerValueAsync(value, cancellationToken); } [CLSCompliant(false)] public override Task WriteValueAsync(ushort? value, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteValueAsync(value, cancellationToken); } return DoWriteValueAsync(value, cancellationToken); } internal Task DoWriteValueAsync(ushort? value, CancellationToken cancellationToken) { if (value.HasValue) { return WriteIntegerValueAsync(value.GetValueOrDefault(), cancellationToken); } return DoWriteNullAsync(cancellationToken); } public override Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteCommentAsync(text, cancellationToken); } return DoWriteCommentAsync(text, cancellationToken); } internal async Task DoWriteCommentAsync(string? text, CancellationToken cancellationToken) { await InternalWriteCommentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync("/*", cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync(text ?? string.Empty, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await _writer.WriteAsync("*/", cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public override Task WriteEndArrayAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteEndArrayAsync(cancellationToken); } return InternalWriteEndAsync(JsonContainerType.Array, cancellationToken); } public override Task WriteEndConstructorAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteEndConstructorAsync(cancellationToken); } return InternalWriteEndAsync(JsonContainerType.Constructor, cancellationToken); } public override Task WriteEndObjectAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteEndObjectAsync(cancellationToken); } return InternalWriteEndAsync(JsonContainerType.Object, cancellationToken); } public override Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default(CancellationToken)) { if (!_safeAsync) { return base.WriteRawValueAsync(json, cancellationToken); } return DoWriteRawValueAsync(json, cancellationToken); } internal Task DoWriteRawValueAsync(string? json, CancellationToken cancellationToken) { UpdateScopeWithFinishedValue(); Task task = AutoCompleteAsync(JsonToken.Undefined, cancellationToken); if (task.IsCompletedSuccessfully()) { return WriteRawAsync(json, cancellationToken); } return DoWriteRawValueAsync(task, json, cancellationToken); } private async Task DoWriteRawValueAsync(Task task, string? json, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteRawAsync(json, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } internal char[] EnsureWriteBuffer(int length, int copyTo) { if (length < 35) { length = 35; } char[] writeBuffer = _writeBuffer; if (writeBuffer == null) { return _writeBuffer = BufferUtils.RentBuffer(_arrayPool, length); } if (writeBuffer.Length >= length) { return writeBuffer; } char[] array = BufferUtils.RentBuffer(_arrayPool, length); if (copyTo != 0) { Array.Copy(writeBuffer, array, copyTo); } BufferUtils.ReturnBuffer(_arrayPool, writeBuffer); _writeBuffer = array; return array; } public JsonTextWriter(TextWriter textWriter) { if (textWriter == null) { throw new ArgumentNullException("textWriter"); } _writer = textWriter; _quoteChar = '"'; _quoteName = true; _indentChar = ' '; _indentation = 2; UpdateCharEscapeFlags(); _safeAsync = GetType() == typeof(JsonTextWriter); } public override void Flush() { _writer.Flush(); } public override void Close() { base.Close(); CloseBufferAndWriter(); } private void CloseBufferAndWriter() { if (_writeBuffer != null) { BufferUtils.ReturnBuffer(_arrayPool, _writeBuffer); _writeBuffer = null; } if (base.CloseOutput) { _writer?.Close(); } } public override void WriteStartObject() { InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object); _writer.Write('{'); } public override void WriteStartArray() { InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array); _writer.Write('['); } public override void WriteStartConstructor(string name) { InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor); _writer.Write("new "); _writer.Write(name); _writer.Write('('); } protected override void WriteEnd(JsonToken token) { switch (token) { case JsonToken.EndObject: _writer.Write('}'); break; case JsonToken.EndArray: _writer.Write(']'); break; case JsonToken.EndConstructor: _writer.Write(')'); break; default: throw JsonWriterException.Create(this, "Invalid JsonToken: " + token, null); } } public override void WritePropertyName(string name) { InternalWritePropertyName(name); WriteEscapedString(name, _quoteName); _writer.Write(':'); } public override void WritePropertyName(string name, bool escape) { InternalWritePropertyName(name); if (escape) { WriteEscapedString(name, _quoteName); } else { if (_quoteName) { _writer.Write(_quoteChar); } _writer.Write(name); if (_quoteName) { _writer.Write(_quoteChar); } } _writer.Write(':'); } internal override void OnStringEscapeHandlingChanged() { UpdateCharEscapeFlags(); } private void UpdateCharEscapeFlags() { _charEscapeFlags = JavaScriptUtils.GetCharEscapeFlags(base.StringEscapeHandling, _quoteChar); } protected override void WriteIndent() { int num = base.Top * _indentation; int num2 = SetIndentChars(); _writer.Write(_indentChars, 0, num2 + Math.Min(num, 12)); while ((num -= 12) > 0) { _writer.Write(_indentChars, num2, Math.Min(num, 12)); } } private int SetIndentChars() { string newLine = _writer.NewLine; int length = newLine.Length; bool flag = _indentChars != null && _indentChars.Length == 12 + length; if (flag) { for (int i = 0; i != length; i++) { if (newLine[i] != _indentChars[i]) { flag = false; break; } } } if (!flag) { _indentChars = (newLine + new string(_indentChar, 12)).ToCharArray(); } return length; } protected override void WriteValueDelimiter() { _writer.Write(','); } protected override void WriteIndentSpace() { _writer.Write(' '); } private void WriteValueInternal(string value, JsonToken token) { _writer.Write(value); } public override void WriteValue(object? value) { if (value is BigInteger bigInteger) { InternalWriteValue(JsonToken.Integer); WriteValueInternal(bigInteger.ToString(CultureInfo.InvariantCulture), JsonToken.String); } else { base.WriteValue(value); } } public override void WriteNull() { InternalWriteValue(JsonToken.Null); WriteValueInternal(JsonConvert.Null, JsonToken.Null); } public override void WriteUndefined() { InternalWriteValue(JsonToken.Undefined); WriteValueInternal(JsonConvert.Undefined, JsonToken.Undefined); } public override void WriteRaw(string? json) { InternalWriteRaw(); _writer.Write(json); } public override void WriteValue(string? value) { InternalWriteValue(JsonToken.String); if (value == null) { WriteValueInternal(JsonConvert.Null, JsonToken.Null); } else { WriteEscapedString(value, quote: true); } } private void WriteEscapedString(string value, bool quote) { EnsureWriteBuffer(); JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, quote, _charEscapeFlags, base.StringEscapeHandling, _arrayPool, ref _writeBuffer); } public override void WriteValue(int value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } [CLSCompliant(false)] public override void WriteValue(uint value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } public override void WriteValue(long value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } [CLSCompliant(false)] public override void WriteValue(ulong value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value, negative: false); } public override void WriteValue(float value) { InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value, base.FloatFormatHandling, QuoteChar, nullable: false), JsonToken.Float); } public override void WriteValue(float? value) { if (!value.HasValue) { WriteNull(); return; } InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value.GetValueOrDefault(), base.FloatFormatHandling, QuoteChar, nullable: true), JsonToken.Float); } public override void WriteValue(double value) { InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value, base.FloatFormatHandling, QuoteChar, nullable: false), JsonToken.Float); } public override void WriteValue(double? value) { if (!value.HasValue) { WriteNull(); return; } InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value.GetValueOrDefault(), base.FloatFormatHandling, QuoteChar, nullable: true), JsonToken.Float); } public override void WriteValue(bool value) { InternalWriteValue(JsonToken.Boolean); WriteValueInternal(JsonConvert.ToString(value), JsonToken.Boolean); } public override void WriteValue(short value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } [CLSCompliant(false)] public override void WriteValue(ushort value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } public override void WriteValue(char value) { InternalWriteValue(JsonToken.String); WriteValueInternal(JsonConvert.ToString(value), JsonToken.String); } public override void WriteValue(byte value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } [CLSCompliant(false)] public override void WriteValue(sbyte value) { InternalWriteValue(JsonToken.Integer); WriteIntegerValue(value); } public override void WriteValue(decimal value) { InternalWriteValue(JsonToken.Float); WriteValueInternal(JsonConvert.ToString(value), JsonToken.Float); } public override void WriteValue(DateTime value) { InternalWriteValue(JsonToken.Date); value = DateTimeUtils.EnsureDateTime(value, base.DateTimeZoneHandling); if (StringUtils.IsNullOrEmpty(base.DateFormatString)) { int count = WriteValueToBuffer(value); _writer.Write(_writeBuffer, 0, count); } else { _writer.Write(_quoteChar); _writer.Write(value.ToString(base.DateFormatString, base.Culture)); _writer.Write(_quoteChar); } } private int WriteValueToBuffer(DateTime value) { EnsureWriteBuffer(); int start = 0; _writeBuffer[start++] = _quoteChar; start = DateTimeUtils.WriteDateTimeString(_writeBuffer, start, value, null, value.Kind, base.DateFormatHandling); _writeBuffer[start++] = _quoteChar; return start; } public override void WriteValue(byte[]? value) { if (value == null) { WriteNull(); return; } InternalWriteValue(JsonToken.Bytes); _writer.Write(_quoteChar); Base64Encoder.Encode(value, 0, value.Length); Base64Encoder.Flush(); _writer.Write(_quoteChar); } public override void WriteValue(DateTimeOffset value) { InternalWriteValue(JsonToken.Date); if (StringUtils.IsNullOrEmpty(base.DateFormatString)) { int count = WriteValueToBuffer(value); _writer.Write(_writeBuffer, 0, count); } else { _writer.Write(_quoteChar); _writer.Write(value.ToString(base.DateFormatString, base.Culture)); _writer.Write(_quoteChar); } } private int WriteValueToBuffer(DateTimeOffset value) { EnsureWriteBuffer(); int start = 0; _writeBuffer[start++] = _quoteChar; start = DateTimeUtils.WriteDateTimeString(_writeBuffer, start, (base.DateFormatHandling == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, base.DateFormatHandling); _writeBuffer[start++] = _quoteChar; return start; } public override void WriteValue(Guid value) { InternalWriteValue(JsonToken.String); string value2 = value.ToString("D", CultureInfo.InvariantCulture); _writer.Write(_quoteChar); _writer.Write(value2); _writer.Write(_quoteChar); } public override void WriteValue(TimeSpan value) { InternalWriteValue(JsonToken.String); string value2 = value.ToString(null, CultureInfo.InvariantCulture); _writer.Write(_quoteChar); _writer.Write(value2); _writer.Write(_quoteChar); } public override void WriteValue(Uri? value) { if (value == null) { WriteNull(); return; } InternalWriteValue(JsonToken.String); WriteEscapedString(value.OriginalString, quote: true); } public override void WriteComment(string? text) { InternalWriteComment(); _writer.Write("/*"); _writer.Write(text); _writer.Write("*/"); } public override void WriteWhitespace(string ws) { InternalWriteWhitespace(ws); _writer.Write(ws); } private void EnsureWriteBuffer() { if (_writeBuffer == null) { _writeBuffer = BufferUtils.RentBuffer(_arrayPool, 35); } } private void WriteIntegerValue(long value) { if (value >= 0 && value <= 9) { _writer.Write((char)(48 + value)); return; } bool flag = value < 0; WriteIntegerValue((ulong)(flag ? (-value) : value), flag); } private void WriteIntegerValue(ulong value, bool negative) { if (!negative && value <= 9) { _writer.Write((char)(48 + value)); return; } int count = WriteNumberToBuffer(value, negative); _writer.Write(_writeBuffer, 0, count); } private int WriteNumberToBuffer(ulong value, bool negative) { if (value <= uint.MaxValue) { return WriteNumberToBuffer((uint)value, negative); } EnsureWriteBuffer(); int num = MathUtils.IntLength(value); if (negative) { num++; _writeBuffer[0] = '-'; } int num2 = num; do { ulong num3 = value / 10; ulong num4 = value - num3 * 10; _writeBuffer[--num2] = (char)(48 + num4); value = num3; } while (value != 0L); return num; } private void WriteIntegerValue(int value) { if (value >= 0 && value <= 9) { _writer.Write((char)(48 + value)); return; } bool flag = value < 0; WriteIntegerValue((uint)(flag ? (-value) : value), flag); } private void WriteIntegerValue(uint value, bool negative) { if (!negative && value <= 9) { _writer.Write((char)(48 + value)); return; } int count = WriteNumberToBuffer(value, negative); _writer.Write(_writeBuffer, 0, count); } private int WriteNumberToBuffer(uint value, bool negative) { EnsureWriteBuffer(); int num = MathUtils.IntLength(value); if (negative) { num++; _writeBuffer[0] = '-'; } int num2 = num; do { uint num3 = value / 10; uint num4 = value - num3 * 10; _writeBuffer[--num2] = (char)(48 + num4); value = num3; } while (value != 0); return num; } } internal enum JsonToken { None, StartObject, StartArray, StartConstructor, PropertyName, Comment, Raw, Integer, Float, String, Boolean, Null, Undefined, EndObject, EndArray, EndConstructor, Date, Bytes } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonValidatingReader : JsonReader, IJsonLineInfo { private class SchemaScope { private readonly JTokenType _tokenType; private readonly IList _schemas; private readonly Dictionary _requiredProperties; public string CurrentPropertyName { get; set; } public int ArrayItemCount { get; set; } public bool IsUniqueArray { get; } public IList UniqueArrayItems { get; } public JTokenWriter CurrentItemWriter { get; set; } public IList Schemas => _schemas; public Dictionary RequiredProperties => _requiredProperties; public JTokenType TokenType => _tokenType; public SchemaScope(JTokenType tokenType, IList schemas) { _tokenType = tokenType; _schemas = schemas; _requiredProperties = schemas.SelectMany(GetRequiredProperties).Distinct().ToDictionary((string p) => p, (string p) => false); if (tokenType == JTokenType.Array && schemas.Any((JsonSchemaModel s) => s.UniqueItems)) { IsUniqueArray = true; UniqueArrayItems = new List(); } } private IEnumerable GetRequiredProperties(JsonSchemaModel schema) { if (schema?.Properties == null) { return Enumerable.Empty(); } return from p in schema.Properties where p.Value.Required select p.Key; } } private readonly JsonReader _reader; private readonly Stack _stack; private JsonSchema _schema; private JsonSchemaModel _model; private SchemaScope _currentScope; private static readonly IList EmptySchemaList = new List(); public override object Value => _reader.Value; public override int Depth => _reader.Depth; public override string Path => _reader.Path; public override char QuoteChar { get { return _reader.QuoteChar; } protected internal set { } } public override JsonToken TokenType => _reader.TokenType; public override Type ValueType => _reader.ValueType; private IList CurrentSchemas => _currentScope.Schemas; private IList CurrentMemberSchemas { get { if (_currentScope == null) { return new List(new JsonSchemaModel[1] { _model }); } if (_currentScope.Schemas == null || _currentScope.Schemas.Count == 0) { return EmptySchemaList; } switch (_currentScope.TokenType) { case JTokenType.None: return _currentScope.Schemas; case JTokenType.Object: { if (_currentScope.CurrentPropertyName == null) { throw new JsonReaderException("CurrentPropertyName has not been set on scope."); } IList list2 = new List(); { foreach (JsonSchemaModel currentSchema in CurrentSchemas) { if (currentSchema.Properties != null && currentSchema.Properties.TryGetValue(_currentScope.CurrentPropertyName, out var value)) { list2.Add(value); } if (currentSchema.PatternProperties != null) { foreach (KeyValuePair patternProperty in currentSchema.PatternProperties) { if (Regex.IsMatch(_currentScope.CurrentPropertyName, patternProperty.Key)) { list2.Add(patternProperty.Value); } } } if (list2.Count == 0 && currentSchema.AllowAdditionalProperties && currentSchema.AdditionalProperties != null) { list2.Add(currentSchema.AdditionalProperties); } } return list2; } } case JTokenType.Array: { IList list = new List(); { foreach (JsonSchemaModel currentSchema2 in CurrentSchemas) { if (!currentSchema2.PositionalItemsValidation) { if (currentSchema2.Items != null && currentSchema2.Items.Count > 0) { list.Add(currentSchema2.Items[0]); } continue; } if (currentSchema2.Items != null && currentSchema2.Items.Count > 0 && currentSchema2.Items.Count > _currentScope.ArrayItemCount - 1) { list.Add(currentSchema2.Items[_currentScope.ArrayItemCount - 1]); } if (currentSchema2.AllowAdditionalItems && currentSchema2.AdditionalItems != null) { list.Add(currentSchema2.AdditionalItems); } } return list; } } case JTokenType.Constructor: return EmptySchemaList; default: throw new ArgumentOutOfRangeException("TokenType", "Unexpected token type: {0}".FormatWith(CultureInfo.InvariantCulture, _currentScope.TokenType)); } } } public JsonSchema Schema { get { return _schema; } set { if (TokenType != 0) { throw new InvalidOperationException("Cannot change schema while validating JSON."); } _schema = value; _model = null; } } public JsonReader Reader => _reader; int IJsonLineInfo.LineNumber { get { if (!(_reader is IJsonLineInfo jsonLineInfo)) { return 0; } return jsonLineInfo.LineNumber; } } int IJsonLineInfo.LinePosition { get { if (!(_reader is IJsonLineInfo jsonLineInfo)) { return 0; } return jsonLineInfo.LinePosition; } } public event ValidationEventHandler ValidationEventHandler; private void Push(SchemaScope scope) { _stack.Push(scope); _currentScope = scope; } private SchemaScope Pop() { SchemaScope result = _stack.Pop(); _currentScope = ((_stack.Count != 0) ? _stack.Peek() : null); return result; } private void RaiseError(string message, JsonSchemaModel schema) { string message2 = (((IJsonLineInfo)this).HasLineInfo() ? (message + " Line {0}, position {1}.".FormatWith(CultureInfo.InvariantCulture, ((IJsonLineInfo)this).LineNumber, ((IJsonLineInfo)this).LinePosition)) : message); OnValidationEvent(new JsonSchemaException(message2, null, Path, ((IJsonLineInfo)this).LineNumber, ((IJsonLineInfo)this).LinePosition)); } private void OnValidationEvent(JsonSchemaException exception) { ValidationEventHandler validationEventHandler = this.ValidationEventHandler; if (validationEventHandler != null) { validationEventHandler(this, new ValidationEventArgs(exception)); return; } throw exception; } public JsonValidatingReader(JsonReader reader) { ValidationUtils.ArgumentNotNull(reader, "reader"); _reader = reader; _stack = new Stack(); } public override void Close() { base.Close(); if (base.CloseInput) { _reader?.Close(); } } private void ValidateNotDisallowed(JsonSchemaModel schema) { if (schema != null) { JsonSchemaType? currentNodeSchemaType = GetCurrentNodeSchemaType(); if (currentNodeSchemaType.HasValue && JsonSchemaGenerator.HasFlag(schema.Disallow, currentNodeSchemaType.GetValueOrDefault())) { RaiseError("Type {0} is disallowed.".FormatWith(CultureInfo.InvariantCulture, currentNodeSchemaType), schema); } } } private JsonSchemaType? GetCurrentNodeSchemaType() { return _reader.TokenType switch { JsonToken.StartObject => JsonSchemaType.Object, JsonToken.StartArray => JsonSchemaType.Array, JsonToken.Integer => JsonSchemaType.Integer, JsonToken.Float => JsonSchemaType.Float, JsonToken.String => JsonSchemaType.String, JsonToken.Boolean => JsonSchemaType.Boolean, JsonToken.Null => JsonSchemaType.Null, _ => null, }; } public override int? ReadAsInt32() { int? result = _reader.ReadAsInt32(); ValidateCurrentToken(); return result; } public override byte[] ReadAsBytes() { byte[]? result = _reader.ReadAsBytes(); ValidateCurrentToken(); return result; } public override decimal? ReadAsDecimal() { decimal? result = _reader.ReadAsDecimal(); ValidateCurrentToken(); return result; } public override double? ReadAsDouble() { double? result = _reader.ReadAsDouble(); ValidateCurrentToken(); return result; } public override bool? ReadAsBoolean() { bool? result = _reader.ReadAsBoolean(); ValidateCurrentToken(); return result; } public override string ReadAsString() { string? result = _reader.ReadAsString(); ValidateCurrentToken(); return result; } public override DateTime? ReadAsDateTime() { DateTime? result = _reader.ReadAsDateTime(); ValidateCurrentToken(); return result; } public override DateTimeOffset? ReadAsDateTimeOffset() { DateTimeOffset? result = _reader.ReadAsDateTimeOffset(); ValidateCurrentToken(); return result; } public override bool Read() { if (!_reader.Read()) { return false; } if (_reader.TokenType == JsonToken.Comment) { return true; } ValidateCurrentToken(); return true; } private void ValidateCurrentToken() { if (_model == null) { JsonSchemaModelBuilder jsonSchemaModelBuilder = new JsonSchemaModelBuilder(); _model = jsonSchemaModelBuilder.Build(_schema); if (!JsonTokenUtils.IsStartToken(_reader.TokenType)) { Push(new SchemaScope(JTokenType.None, CurrentMemberSchemas)); } } switch (_reader.TokenType) { case JsonToken.StartObject: { ProcessValue(); IList schemas2 = CurrentMemberSchemas.Where(ValidateObject).ToList(); Push(new SchemaScope(JTokenType.Object, schemas2)); WriteToken(CurrentSchemas); break; } case JsonToken.StartArray: { ProcessValue(); IList schemas = CurrentMemberSchemas.Where(ValidateArray).ToList(); Push(new SchemaScope(JTokenType.Array, schemas)); WriteToken(CurrentSchemas); break; } case JsonToken.StartConstructor: ProcessValue(); Push(new SchemaScope(JTokenType.Constructor, null)); WriteToken(CurrentSchemas); break; case JsonToken.PropertyName: WriteToken(CurrentSchemas); { foreach (JsonSchemaModel currentSchema in CurrentSchemas) { ValidatePropertyName(currentSchema); } break; } case JsonToken.Raw: ProcessValue(); break; case JsonToken.Integer: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema in CurrentMemberSchemas) { ValidateInteger(currentMemberSchema); } break; } case JsonToken.Float: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema2 in CurrentMemberSchemas) { ValidateFloat(currentMemberSchema2); } break; } case JsonToken.String: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema3 in CurrentMemberSchemas) { ValidateString(currentMemberSchema3); } break; } case JsonToken.Boolean: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema4 in CurrentMemberSchemas) { ValidateBoolean(currentMemberSchema4); } break; } case JsonToken.Null: ProcessValue(); WriteToken(CurrentMemberSchemas); { foreach (JsonSchemaModel currentMemberSchema5 in CurrentMemberSchemas) { ValidateNull(currentMemberSchema5); } break; } case JsonToken.EndObject: WriteToken(CurrentSchemas); foreach (JsonSchemaModel currentSchema2 in CurrentSchemas) { ValidateEndObject(currentSchema2); } Pop(); break; case JsonToken.EndArray: WriteToken(CurrentSchemas); foreach (JsonSchemaModel currentSchema3 in CurrentSchemas) { ValidateEndArray(currentSchema3); } Pop(); break; case JsonToken.EndConstructor: WriteToken(CurrentSchemas); Pop(); break; case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: WriteToken(CurrentMemberSchemas); break; default: throw new ArgumentOutOfRangeException(); case JsonToken.None: break; } } private void WriteToken(IList schemas) { foreach (SchemaScope item in _stack) { bool flag = item.TokenType == JTokenType.Array && item.IsUniqueArray && item.ArrayItemCount > 0; if (!flag && !schemas.Any((JsonSchemaModel s) => s.Enum != null)) { continue; } if (item.CurrentItemWriter == null) { if (JsonTokenUtils.IsEndToken(_reader.TokenType)) { continue; } item.CurrentItemWriter = new JTokenWriter(); } item.CurrentItemWriter.WriteToken(_reader, writeChildren: false); if (item.CurrentItemWriter.Top != 0 || _reader.TokenType == JsonToken.PropertyName) { continue; } JToken token = item.CurrentItemWriter.Token; item.CurrentItemWriter = null; if (flag) { if (item.UniqueArrayItems.Contains(token, JToken.EqualityComparer)) { RaiseError("Non-unique array item at index {0}.".FormatWith(CultureInfo.InvariantCulture, item.ArrayItemCount - 1), item.Schemas.First((JsonSchemaModel s) => s.UniqueItems)); } item.UniqueArrayItems.Add(token); } else { if (!schemas.Any((JsonSchemaModel s) => s.Enum != null)) { continue; } foreach (JsonSchemaModel schema in schemas) { if (schema.Enum != null && !schema.Enum.ContainsValue(token, JToken.EqualityComparer)) { StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); token.WriteTo(new JsonTextWriter(stringWriter)); RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, stringWriter.ToString()), schema); } } } } } private void ValidateEndObject(JsonSchemaModel schema) { if (schema == null) { return; } Dictionary requiredProperties = _currentScope.RequiredProperties; if (requiredProperties != null && requiredProperties.Values.Any((bool v) => !v)) { IEnumerable values = from kv in requiredProperties where !kv.Value select kv.Key; RaiseError("Required properties are missing from object: {0}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", values)), schema); } } private void ValidateEndArray(JsonSchemaModel schema) { if (schema != null) { int arrayItemCount = _currentScope.ArrayItemCount; if (schema.MaximumItems.HasValue && arrayItemCount > schema.MaximumItems) { RaiseError("Array item count {0} exceeds maximum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MaximumItems), schema); } if (schema.MinimumItems.HasValue && arrayItemCount < schema.MinimumItems) { RaiseError("Array item count {0} is less than minimum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MinimumItems), schema); } } } private void ValidateNull(JsonSchemaModel schema) { if (schema != null && TestType(schema, JsonSchemaType.Null)) { ValidateNotDisallowed(schema); } } private void ValidateBoolean(JsonSchemaModel schema) { if (schema != null && TestType(schema, JsonSchemaType.Boolean)) { ValidateNotDisallowed(schema); } } private void ValidateString(JsonSchemaModel schema) { if (schema == null || !TestType(schema, JsonSchemaType.String)) { return; } ValidateNotDisallowed(schema); string text = _reader.Value.ToString(); if (schema.MaximumLength.HasValue && text.Length > schema.MaximumLength) { RaiseError("String '{0}' exceeds maximum length of {1}.".FormatWith(CultureInfo.InvariantCulture, text, schema.MaximumLength), schema); } if (schema.MinimumLength.HasValue && text.Length < schema.MinimumLength) { RaiseError("String '{0}' is less than minimum length of {1}.".FormatWith(CultureInfo.InvariantCulture, text, schema.MinimumLength), schema); } if (schema.Patterns == null) { return; } foreach (string pattern in schema.Patterns) { if (!Regex.IsMatch(text, pattern)) { RaiseError("String '{0}' does not match regex pattern '{1}'.".FormatWith(CultureInfo.InvariantCulture, text, pattern), schema); } } } private void ValidateInteger(JsonSchemaModel schema) { if (schema == null || !TestType(schema, JsonSchemaType.Integer)) { return; } ValidateNotDisallowed(schema); object value = _reader.Value; if (schema.Maximum.HasValue) { if (JValue.Compare(JTokenType.Integer, value, schema.Maximum) > 0) { RaiseError("Integer {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema); } if (schema.ExclusiveMaximum && JValue.Compare(JTokenType.Integer, value, schema.Maximum) == 0) { RaiseError("Integer {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema); } } if (schema.Minimum.HasValue) { if (JValue.Compare(JTokenType.Integer, value, schema.Minimum) < 0) { RaiseError("Integer {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema); } if (schema.ExclusiveMinimum && JValue.Compare(JTokenType.Integer, value, schema.Minimum) == 0) { RaiseError("Integer {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema); } } if (schema.DivisibleBy.HasValue && ((!(value is BigInteger bigInteger)) ? (!IsZero((double)Convert.ToInt64(value, CultureInfo.InvariantCulture) % schema.DivisibleBy.GetValueOrDefault())) : (Math.Abs(schema.DivisibleBy.Value - Math.Truncate(schema.DivisibleBy.Value)).Equals(0.0) ? (bigInteger % new BigInteger(schema.DivisibleBy.Value) != 0L) : (bigInteger != 0L)))) { RaiseError("Integer {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.DivisibleBy), schema); } } private void ProcessValue() { if (_currentScope == null || _currentScope.TokenType != JTokenType.Array) { return; } _currentScope.ArrayItemCount++; foreach (JsonSchemaModel currentSchema in CurrentSchemas) { if (currentSchema != null && currentSchema.PositionalItemsValidation && !currentSchema.AllowAdditionalItems && (currentSchema.Items == null || _currentScope.ArrayItemCount - 1 >= currentSchema.Items.Count)) { RaiseError("Index {0} has not been defined and the schema does not allow additional items.".FormatWith(CultureInfo.InvariantCulture, _currentScope.ArrayItemCount), currentSchema); } } } private void ValidateFloat(JsonSchemaModel schema) { if (schema == null || !TestType(schema, JsonSchemaType.Float)) { return; } ValidateNotDisallowed(schema); double num = Convert.ToDouble(_reader.Value, CultureInfo.InvariantCulture); if (schema.Maximum.HasValue) { if (num > schema.Maximum) { RaiseError("Float {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.Maximum), schema); } if (schema.ExclusiveMaximum && num == schema.Maximum) { RaiseError("Float {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.Maximum), schema); } } if (schema.Minimum.HasValue) { if (num < schema.Minimum) { RaiseError("Float {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.Minimum), schema); } if (schema.ExclusiveMinimum && num == schema.Minimum) { RaiseError("Float {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.Minimum), schema); } } if (schema.DivisibleBy.HasValue && !IsZero(FloatingPointRemainder(num, schema.DivisibleBy.GetValueOrDefault()))) { RaiseError("Float {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(num), schema.DivisibleBy), schema); } } private static double FloatingPointRemainder(double dividend, double divisor) { return dividend - Math.Floor(dividend / divisor) * divisor; } private static bool IsZero(double value) { return Math.Abs(value) < 4.440892098500626E-15; } private void ValidatePropertyName(JsonSchemaModel schema) { if (schema != null) { string text = Convert.ToString(_reader.Value, CultureInfo.InvariantCulture); if (_currentScope.RequiredProperties.ContainsKey(text)) { _currentScope.RequiredProperties[text] = true; } if (!schema.AllowAdditionalProperties && !IsPropertyDefinied(schema, text)) { RaiseError("Property '{0}' has not been defined and the schema does not allow additional properties.".FormatWith(CultureInfo.InvariantCulture, text), schema); } _currentScope.CurrentPropertyName = text; } } private bool IsPropertyDefinied(JsonSchemaModel schema, string propertyName) { if (schema.Properties != null && schema.Properties.ContainsKey(propertyName)) { return true; } if (schema.PatternProperties != null) { foreach (string key in schema.PatternProperties.Keys) { if (Regex.IsMatch(propertyName, key)) { return true; } } } return false; } private bool ValidateArray(JsonSchemaModel schema) { if (schema == null) { return true; } return TestType(schema, JsonSchemaType.Array); } private bool ValidateObject(JsonSchemaModel schema) { if (schema == null) { return true; } return TestType(schema, JsonSchemaType.Object); } private bool TestType(JsonSchemaModel currentSchema, JsonSchemaType currentType) { if (!JsonSchemaGenerator.HasFlag(currentSchema.Type, currentType)) { RaiseError("Invalid type. Expected {0} but got {1}.".FormatWith(CultureInfo.InvariantCulture, currentSchema.Type, currentType), currentSchema); return false; } return true; } bool IJsonLineInfo.HasLineInfo() { if (_reader is IJsonLineInfo jsonLineInfo) { return jsonLineInfo.HasLineInfo(); } return false; } } internal abstract class JsonWriter : IDisposable { internal enum State { Start, Property, ObjectStart, Object, ArrayStart, Array, ConstructorStart, Constructor, Closed, Error } private static readonly State[][] StateArray; internal static readonly State[][] StateArrayTemplate; private List? _stack; private JsonPosition _currentPosition; private State _currentState; private Formatting _formatting; private DateFormatHandling _dateFormatHandling; private DateTimeZoneHandling _dateTimeZoneHandling; private StringEscapeHandling _stringEscapeHandling; private FloatFormatHandling _floatFormatHandling; private string? _dateFormatString; private CultureInfo? _culture; public bool CloseOutput { get; set; } public bool AutoCompleteOnClose { get; set; } protected internal int Top { get { int num = _stack?.Count ?? 0; if (Peek() != 0) { num++; } return num; } } public WriteState WriteState { get { switch (_currentState) { case State.Error: return WriteState.Error; case State.Closed: return WriteState.Closed; case State.ObjectStart: case State.Object: return WriteState.Object; case State.ArrayStart: case State.Array: return WriteState.Array; case State.ConstructorStart: case State.Constructor: return WriteState.Constructor; case State.Property: return WriteState.Property; case State.Start: return WriteState.Start; default: throw JsonWriterException.Create(this, "Invalid state: " + _currentState, null); } } } internal string ContainerPath { get { if (_currentPosition.Type == JsonContainerType.None || _stack == null) { return string.Empty; } return JsonPosition.BuildPath(_stack, null); } } public string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public Formatting Formatting { get { return _formatting; } set { if (value < Formatting.None || value > Formatting.Indented) { throw new ArgumentOutOfRangeException("value"); } _formatting = value; } } public DateFormatHandling DateFormatHandling { get { return _dateFormatHandling; } set { if (value < DateFormatHandling.IsoDateFormat || value > DateFormatHandling.MicrosoftDateFormat) { throw new ArgumentOutOfRangeException("value"); } _dateFormatHandling = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling; } set { if (value < StringEscapeHandling.Default || value > StringEscapeHandling.EscapeHtml) { throw new ArgumentOutOfRangeException("value"); } _stringEscapeHandling = value; OnStringEscapeHandlingChanged(); } } public FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling; } set { if (value < FloatFormatHandling.String || value > FloatFormatHandling.DefaultValue) { throw new ArgumentOutOfRangeException("value"); } _floatFormatHandling = value; } } public string? DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } internal Task AutoCompleteAsync(JsonToken tokenBeingWritten, CancellationToken cancellationToken) { State currentState = _currentState; State state = StateArray[(int)tokenBeingWritten][(int)currentState]; if (state == State.Error) { throw JsonWriterException.Create(this, "Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), currentState.ToString()), null); } _currentState = state; if (_formatting == Formatting.Indented) { switch (currentState) { case State.Property: return WriteIndentSpaceAsync(cancellationToken); case State.ArrayStart: case State.ConstructorStart: return WriteIndentAsync(cancellationToken); case State.Array: case State.Constructor: if (tokenBeingWritten != JsonToken.Comment) { return AutoCompleteAsync(cancellationToken); } return WriteIndentAsync(cancellationToken); case State.Object: switch (tokenBeingWritten) { case JsonToken.PropertyName: return AutoCompleteAsync(cancellationToken); default: return WriteValueDelimiterAsync(cancellationToken); case JsonToken.Comment: break; } break; default: if (tokenBeingWritten == JsonToken.PropertyName) { return WriteIndentAsync(cancellationToken); } break; case State.Start: break; } } else if (tokenBeingWritten != JsonToken.Comment) { switch (currentState) { case State.Object: case State.Array: case State.Constructor: return WriteValueDelimiterAsync(cancellationToken); } } return AsyncUtils.CompletedTask; } private async Task AutoCompleteAsync(CancellationToken cancellationToken) { await WriteValueDelimiterAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await WriteIndentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public virtual Task CloseAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } Close(); return AsyncUtils.CompletedTask; } public virtual Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } Flush(); return AsyncUtils.CompletedTask; } protected virtual Task WriteEndAsync(JsonToken token, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEnd(token); return AsyncUtils.CompletedTask; } protected virtual Task WriteIndentAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteIndent(); return AsyncUtils.CompletedTask; } protected virtual Task WriteValueDelimiterAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValueDelimiter(); return AsyncUtils.CompletedTask; } protected virtual Task WriteIndentSpaceAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteIndentSpace(); return AsyncUtils.CompletedTask; } public virtual Task WriteRawAsync(string? json, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteRaw(json); return AsyncUtils.CompletedTask; } public virtual Task WriteEndAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEnd(); return AsyncUtils.CompletedTask; } internal Task WriteEndInternalAsync(CancellationToken cancellationToken) { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: return WriteEndObjectAsync(cancellationToken); case JsonContainerType.Array: return WriteEndArrayAsync(cancellationToken); case JsonContainerType.Constructor: return WriteEndConstructorAsync(cancellationToken); default: if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } throw JsonWriterException.Create(this, "Unexpected type when writing end: " + jsonContainerType, null); } } internal Task InternalWriteEndAsync(JsonContainerType type, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } int levelsToComplete = CalculateLevelsToComplete(type); while (levelsToComplete-- > 0) { JsonToken closeTokenForType = GetCloseTokenForType(Pop()); Task task2; if (_currentState == State.Property) { task2 = WriteNullAsync(cancellationToken); if (!task2.IsCompletedSuccessfully()) { return AwaitProperty(task2, levelsToComplete, closeTokenForType, cancellationToken); } } if (_formatting == Formatting.Indented && _currentState != State.ObjectStart && _currentState != State.ArrayStart) { task2 = WriteIndentAsync(cancellationToken); if (!task2.IsCompletedSuccessfully()) { return AwaitIndent(task2, levelsToComplete, closeTokenForType, cancellationToken); } } task2 = WriteEndAsync(closeTokenForType, cancellationToken); if (!task2.IsCompletedSuccessfully()) { return AwaitEnd(task2, levelsToComplete, cancellationToken); } UpdateCurrentState(); } return AsyncUtils.CompletedTask; async Task AwaitEnd(Task task, int LevelsToComplete, CancellationToken CancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); UpdateCurrentState(); await AwaitRemaining(LevelsToComplete, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } async Task AwaitIndent(Task task, int LevelsToComplete, JsonToken token, CancellationToken CancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteEndAsync(token, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); UpdateCurrentState(); await AwaitRemaining(LevelsToComplete, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } async Task AwaitProperty(Task task, int LevelsToComplete, JsonToken token, CancellationToken CancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); if (_formatting == Formatting.Indented && _currentState != State.ObjectStart && _currentState != State.ArrayStart) { await WriteIndentAsync(CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await WriteEndAsync(token, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); UpdateCurrentState(); await AwaitRemaining(LevelsToComplete, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } async Task AwaitRemaining(int LevelsToComplete, CancellationToken CancellationToken) { while (LevelsToComplete-- > 0) { JsonToken token2 = GetCloseTokenForType(Pop()); if (_currentState == State.Property) { await WriteNullAsync(CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (_formatting == Formatting.Indented && _currentState != State.ObjectStart && _currentState != State.ArrayStart) { await WriteIndentAsync(CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await WriteEndAsync(token2, CancellationToken).ConfigureAwait(continueOnCapturedContext: false); UpdateCurrentState(); } } } public virtual Task WriteEndArrayAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEndArray(); return AsyncUtils.CompletedTask; } public virtual Task WriteEndConstructorAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEndConstructor(); return AsyncUtils.CompletedTask; } public virtual Task WriteEndObjectAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteEndObject(); return AsyncUtils.CompletedTask; } public virtual Task WriteNullAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteNull(); return AsyncUtils.CompletedTask; } public virtual Task WritePropertyNameAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WritePropertyName(name); return AsyncUtils.CompletedTask; } public virtual Task WritePropertyNameAsync(string name, bool escape, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WritePropertyName(name, escape); return AsyncUtils.CompletedTask; } internal Task InternalWritePropertyNameAsync(string name, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } _currentPosition.PropertyName = name; return AutoCompleteAsync(JsonToken.PropertyName, cancellationToken); } public virtual Task WriteStartArrayAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteStartArray(); return AsyncUtils.CompletedTask; } internal async Task InternalWriteStartAsync(JsonToken token, JsonContainerType container, CancellationToken cancellationToken) { UpdateScopeWithFinishedValue(); await AutoCompleteAsync(token, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); Push(container); } public virtual Task WriteCommentAsync(string? text, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteComment(text); return AsyncUtils.CompletedTask; } internal Task InternalWriteCommentAsync(CancellationToken cancellationToken) { return AutoCompleteAsync(JsonToken.Comment, cancellationToken); } public virtual Task WriteRawValueAsync(string? json, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteRawValue(json); return AsyncUtils.CompletedTask; } public virtual Task WriteStartConstructorAsync(string name, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteStartConstructor(name); return AsyncUtils.CompletedTask; } public virtual Task WriteStartObjectAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteStartObject(); return AsyncUtils.CompletedTask; } public Task WriteTokenAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return WriteTokenAsync(reader, writeChildren: true, cancellationToken); } public Task WriteTokenAsync(JsonReader reader, bool writeChildren, CancellationToken cancellationToken = default(CancellationToken)) { ValidationUtils.ArgumentNotNull(reader, "reader"); return WriteTokenAsync(reader, writeChildren, writeDateConstructorAsDate: true, writeComments: true, cancellationToken); } public Task WriteTokenAsync(JsonToken token, CancellationToken cancellationToken = default(CancellationToken)) { return WriteTokenAsync(token, null, cancellationToken); } public Task WriteTokenAsync(JsonToken token, object? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } switch (token) { case JsonToken.None: return AsyncUtils.CompletedTask; case JsonToken.StartObject: return WriteStartObjectAsync(cancellationToken); case JsonToken.StartArray: return WriteStartArrayAsync(cancellationToken); case JsonToken.StartConstructor: ValidationUtils.ArgumentNotNull(value, "value"); return WriteStartConstructorAsync(value.ToString(), cancellationToken); case JsonToken.PropertyName: ValidationUtils.ArgumentNotNull(value, "value"); return WritePropertyNameAsync(value.ToString(), cancellationToken); case JsonToken.Comment: return WriteCommentAsync(value?.ToString(), cancellationToken); case JsonToken.Integer: ValidationUtils.ArgumentNotNull(value, "value"); if (!(value is BigInteger bigInteger)) { return WriteValueAsync(Convert.ToInt64(value, CultureInfo.InvariantCulture), cancellationToken); } return WriteValueAsync(bigInteger, cancellationToken); case JsonToken.Float: ValidationUtils.ArgumentNotNull(value, "value"); if (value is decimal value4) { return WriteValueAsync(value4, cancellationToken); } if (value is double value5) { return WriteValueAsync(value5, cancellationToken); } if (value is float value6) { return WriteValueAsync(value6, cancellationToken); } return WriteValueAsync(Convert.ToDouble(value, CultureInfo.InvariantCulture), cancellationToken); case JsonToken.String: ValidationUtils.ArgumentNotNull(value, "value"); return WriteValueAsync(value.ToString(), cancellationToken); case JsonToken.Boolean: ValidationUtils.ArgumentNotNull(value, "value"); return WriteValueAsync(Convert.ToBoolean(value, CultureInfo.InvariantCulture), cancellationToken); case JsonToken.Null: return WriteNullAsync(cancellationToken); case JsonToken.Undefined: return WriteUndefinedAsync(cancellationToken); case JsonToken.EndObject: return WriteEndObjectAsync(cancellationToken); case JsonToken.EndArray: return WriteEndArrayAsync(cancellationToken); case JsonToken.EndConstructor: return WriteEndConstructorAsync(cancellationToken); case JsonToken.Date: ValidationUtils.ArgumentNotNull(value, "value"); if (value is DateTimeOffset value3) { return WriteValueAsync(value3, cancellationToken); } return WriteValueAsync(Convert.ToDateTime(value, CultureInfo.InvariantCulture), cancellationToken); case JsonToken.Raw: return WriteRawValueAsync(value?.ToString(), cancellationToken); case JsonToken.Bytes: ValidationUtils.ArgumentNotNull(value, "value"); if (value is Guid value2) { return WriteValueAsync(value2, cancellationToken); } return WriteValueAsync((byte[])value, cancellationToken); default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("token", token, "Unexpected token type."); } } internal virtual async Task WriteTokenAsync(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments, CancellationToken cancellationToken) { int initialDepth = CalculateWriteTokenInitialDepth(reader); bool flag; do { if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { await WriteConstructorDateAsync(reader, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else if (writeComments || reader.TokenType != JsonToken.Comment) { await WriteTokenAsync(reader.TokenType, reader.Value, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } flag = initialDepth - 1 < reader.Depth - (JsonTokenUtils.IsEndToken(reader.TokenType) ? 1 : 0) && writeChildren; if (flag) { flag = await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } while (flag); if (IsWriteTokenIncomplete(reader, writeChildren, initialDepth)) { throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); } } internal async Task WriteTokenSyncReadingAsync(JsonReader reader, CancellationToken cancellationToken) { int initialDepth = CalculateWriteTokenInitialDepth(reader); bool flag; do { if (reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { WriteConstructorDate(reader); } else { WriteToken(reader.TokenType, reader.Value); } flag = initialDepth - 1 < reader.Depth - (JsonTokenUtils.IsEndToken(reader.TokenType) ? 1 : 0); if (flag) { flag = await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } while (flag); if (initialDepth < CalculateWriteTokenFinalDepth(reader)) { throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); } } private async Task WriteConstructorDateAsync(JsonReader reader, CancellationToken cancellationToken) { if (!(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null); } if (reader.TokenType != JsonToken.Integer) { throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null); } DateTime date = DateTimeUtils.ConvertJavaScriptTicksToDateTime((long)reader.Value); if (!(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null); } if (reader.TokenType != JsonToken.EndConstructor) { throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected EndConstructor, got " + reader.TokenType, null); } await WriteValueAsync(date, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public virtual Task WriteValueAsync(bool value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(bool? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(byte value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(byte? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(byte[]? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(char value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(char? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(DateTime value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(DateTime? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(DateTimeOffset value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(DateTimeOffset? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(decimal value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(decimal? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(double value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(double? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(float value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(float? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(Guid value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(Guid? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(int value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(int? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(long value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(long? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(object? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(sbyte value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(sbyte? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(short value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(short? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(string? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(TimeSpan value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(TimeSpan? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(uint value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(uint? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(ulong value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(ulong? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteValueAsync(Uri? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(ushort value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } [CLSCompliant(false)] public virtual Task WriteValueAsync(ushort? value, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteValue(value); return AsyncUtils.CompletedTask; } public virtual Task WriteUndefinedAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteUndefined(); return AsyncUtils.CompletedTask; } public virtual Task WriteWhitespaceAsync(string ws, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } WriteWhitespace(ws); return AsyncUtils.CompletedTask; } internal Task InternalWriteValueAsync(JsonToken token, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } UpdateScopeWithFinishedValue(); return AutoCompleteAsync(token, cancellationToken); } protected Task SetWriteStateAsync(JsonToken token, object value, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } switch (token) { case JsonToken.StartObject: return InternalWriteStartAsync(token, JsonContainerType.Object, cancellationToken); case JsonToken.StartArray: return InternalWriteStartAsync(token, JsonContainerType.Array, cancellationToken); case JsonToken.StartConstructor: return InternalWriteStartAsync(token, JsonContainerType.Constructor, cancellationToken); case JsonToken.PropertyName: if (!(value is string name)) { throw new ArgumentException("A name is required when setting property name state.", "value"); } return InternalWritePropertyNameAsync(name, cancellationToken); case JsonToken.Comment: return InternalWriteCommentAsync(cancellationToken); case JsonToken.Raw: return AsyncUtils.CompletedTask; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: return InternalWriteValueAsync(token, cancellationToken); case JsonToken.EndObject: return InternalWriteEndAsync(JsonContainerType.Object, cancellationToken); case JsonToken.EndArray: return InternalWriteEndAsync(JsonContainerType.Array, cancellationToken); case JsonToken.EndConstructor: return InternalWriteEndAsync(JsonContainerType.Constructor, cancellationToken); default: throw new ArgumentOutOfRangeException("token"); } } internal static Task WriteValueAsync(JsonWriter writer, PrimitiveTypeCode typeCode, object value, CancellationToken cancellationToken) { while (true) { switch (typeCode) { case PrimitiveTypeCode.Char: return writer.WriteValueAsync((char)value, cancellationToken); case PrimitiveTypeCode.CharNullable: return writer.WriteValueAsync((value == null) ? null : new char?((char)value), cancellationToken); case PrimitiveTypeCode.Boolean: return writer.WriteValueAsync((bool)value, cancellationToken); case PrimitiveTypeCode.BooleanNullable: return writer.WriteValueAsync((value == null) ? null : new bool?((bool)value), cancellationToken); case PrimitiveTypeCode.SByte: return writer.WriteValueAsync((sbyte)value, cancellationToken); case PrimitiveTypeCode.SByteNullable: return writer.WriteValueAsync((value == null) ? null : new sbyte?((sbyte)value), cancellationToken); case PrimitiveTypeCode.Int16: return writer.WriteValueAsync((short)value, cancellationToken); case PrimitiveTypeCode.Int16Nullable: return writer.WriteValueAsync((value == null) ? null : new short?((short)value), cancellationToken); case PrimitiveTypeCode.UInt16: return writer.WriteValueAsync((ushort)value, cancellationToken); case PrimitiveTypeCode.UInt16Nullable: return writer.WriteValueAsync((value == null) ? null : new ushort?((ushort)value), cancellationToken); case PrimitiveTypeCode.Int32: return writer.WriteValueAsync((int)value, cancellationToken); case PrimitiveTypeCode.Int32Nullable: return writer.WriteValueAsync((value == null) ? null : new int?((int)value), cancellationToken); case PrimitiveTypeCode.Byte: return writer.WriteValueAsync((byte)value, cancellationToken); case PrimitiveTypeCode.ByteNullable: return writer.WriteValueAsync((value == null) ? null : new byte?((byte)value), cancellationToken); case PrimitiveTypeCode.UInt32: return writer.WriteValueAsync((uint)value, cancellationToken); case PrimitiveTypeCode.UInt32Nullable: return writer.WriteValueAsync((value == null) ? null : new uint?((uint)value), cancellationToken); case PrimitiveTypeCode.Int64: return writer.WriteValueAsync((long)value, cancellationToken); case PrimitiveTypeCode.Int64Nullable: return writer.WriteValueAsync((value == null) ? null : new long?((long)value), cancellationToken); case PrimitiveTypeCode.UInt64: return writer.WriteValueAsync((ulong)value, cancellationToken); case PrimitiveTypeCode.UInt64Nullable: return writer.WriteValueAsync((value == null) ? null : new ulong?((ulong)value), cancellationToken); case PrimitiveTypeCode.Single: return writer.WriteValueAsync((float)value, cancellationToken); case PrimitiveTypeCode.SingleNullable: return writer.WriteValueAsync((value == null) ? null : new float?((float)value), cancellationToken); case PrimitiveTypeCode.Double: return writer.WriteValueAsync((double)value, cancellationToken); case PrimitiveTypeCode.DoubleNullable: return writer.WriteValueAsync((value == null) ? null : new double?((double)value), cancellationToken); case PrimitiveTypeCode.DateTime: return writer.WriteValueAsync((DateTime)value, cancellationToken); case PrimitiveTypeCode.DateTimeNullable: return writer.WriteValueAsync((value == null) ? null : new DateTime?((DateTime)value), cancellationToken); case PrimitiveTypeCode.DateTimeOffset: return writer.WriteValueAsync((DateTimeOffset)value, cancellationToken); case PrimitiveTypeCode.DateTimeOffsetNullable: return writer.WriteValueAsync((value == null) ? null : new DateTimeOffset?((DateTimeOffset)value), cancellationToken); case PrimitiveTypeCode.Decimal: return writer.WriteValueAsync((decimal)value, cancellationToken); case PrimitiveTypeCode.DecimalNullable: return writer.WriteValueAsync((value == null) ? null : new decimal?((decimal)value), cancellationToken); case PrimitiveTypeCode.Guid: return writer.WriteValueAsync((Guid)value, cancellationToken); case PrimitiveTypeCode.GuidNullable: return writer.WriteValueAsync((value == null) ? null : new Guid?((Guid)value), cancellationToken); case PrimitiveTypeCode.TimeSpan: return writer.WriteValueAsync((TimeSpan)value, cancellationToken); case PrimitiveTypeCode.TimeSpanNullable: return writer.WriteValueAsync((value == null) ? null : new TimeSpan?((TimeSpan)value), cancellationToken); case PrimitiveTypeCode.BigInteger: return writer.WriteValueAsync((BigInteger)value, cancellationToken); case PrimitiveTypeCode.BigIntegerNullable: return writer.WriteValueAsync((value == null) ? null : new BigInteger?((BigInteger)value), cancellationToken); case PrimitiveTypeCode.Uri: return writer.WriteValueAsync((Uri)value, cancellationToken); case PrimitiveTypeCode.String: return writer.WriteValueAsync((string)value, cancellationToken); case PrimitiveTypeCode.Bytes: return writer.WriteValueAsync((byte[])value, cancellationToken); case PrimitiveTypeCode.DBNull: return writer.WriteNullAsync(cancellationToken); } if (value is IConvertible convertible) { ResolveConvertibleValue(convertible, out typeCode, out value); continue; } if (value == null) { return writer.WriteNullAsync(cancellationToken); } throw CreateUnsupportedTypeException(writer, value); } } internal static State[][] BuildStateArray() { List list = StateArrayTemplate.ToList(); State[] item = StateArrayTemplate[0]; State[] item2 = StateArrayTemplate[7]; ulong[] values = EnumUtils.GetEnumValuesAndNames(typeof(JsonToken)).Values; foreach (ulong num in values) { if (list.Count <= (int)num) { JsonToken jsonToken = (JsonToken)num; if ((uint)(jsonToken - 7) <= 5u || (uint)(jsonToken - 16) <= 1u) { list.Add(item2); } else { list.Add(item); } } } return list.ToArray(); } static JsonWriter() { StateArrayTemplate = new State[8][] { new State[10] { State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error }, new State[10] { State.ObjectStart, State.ObjectStart, State.Error, State.Error, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.ObjectStart, State.Error, State.Error }, new State[10] { State.ArrayStart, State.ArrayStart, State.Error, State.Error, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.ArrayStart, State.Error, State.Error }, new State[10] { State.ConstructorStart, State.ConstructorStart, State.Error, State.Error, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.Error, State.Error }, new State[10] { State.Property, State.Error, State.Property, State.Property, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error }, new State[10] { State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error }, new State[10] { State.Start, State.Property, State.ObjectStart, State.Object, State.ArrayStart, State.Array, State.Constructor, State.Constructor, State.Error, State.Error }, new State[10] { State.Start, State.Object, State.Error, State.Error, State.Array, State.Array, State.Constructor, State.Constructor, State.Error, State.Error } }; StateArray = BuildStateArray(); } internal virtual void OnStringEscapeHandlingChanged() { } protected JsonWriter() { _currentState = State.Start; _formatting = Formatting.None; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; CloseOutput = true; AutoCompleteOnClose = true; } internal void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void Push(JsonContainerType value) { if (_currentPosition.Type != 0) { if (_stack == null) { _stack = new List(); } _stack.Add(_currentPosition); } _currentPosition = new JsonPosition(value); } private JsonContainerType Pop() { JsonPosition currentPosition = _currentPosition; if (_stack != null && _stack.Count > 0) { _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { _currentPosition = default(JsonPosition); } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract void Flush(); public virtual void Close() { if (AutoCompleteOnClose) { AutoCompleteAll(); } } public virtual void WriteStartObject() { InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object); } public virtual void WriteEndObject() { InternalWriteEnd(JsonContainerType.Object); } public virtual void WriteStartArray() { InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array); } public virtual void WriteEndArray() { InternalWriteEnd(JsonContainerType.Array); } public virtual void WriteStartConstructor(string name) { InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor); } public virtual void WriteEndConstructor() { InternalWriteEnd(JsonContainerType.Constructor); } public virtual void WritePropertyName(string name) { InternalWritePropertyName(name); } public virtual void WritePropertyName(string name, bool escape) { WritePropertyName(name); } public virtual void WriteEnd() { WriteEnd(Peek()); } public void WriteToken(JsonReader reader) { WriteToken(reader, writeChildren: true); } public void WriteToken(JsonReader reader, bool writeChildren) { ValidationUtils.ArgumentNotNull(reader, "reader"); WriteToken(reader, writeChildren, writeDateConstructorAsDate: true, writeComments: true); } public void WriteToken(JsonToken token, object? value) { switch (token) { case JsonToken.StartObject: WriteStartObject(); break; case JsonToken.StartArray: WriteStartArray(); break; case JsonToken.StartConstructor: ValidationUtils.ArgumentNotNull(value, "value"); WriteStartConstructor(value.ToString()); break; case JsonToken.PropertyName: ValidationUtils.ArgumentNotNull(value, "value"); WritePropertyName(value.ToString()); break; case JsonToken.Comment: WriteComment(value?.ToString()); break; case JsonToken.Integer: ValidationUtils.ArgumentNotNull(value, "value"); if (value is BigInteger bigInteger) { WriteValue(bigInteger); } else { WriteValue(Convert.ToInt64(value, CultureInfo.InvariantCulture)); } break; case JsonToken.Float: ValidationUtils.ArgumentNotNull(value, "value"); if (value is decimal value3) { WriteValue(value3); } else if (value is double value4) { WriteValue(value4); } else if (value is float value5) { WriteValue(value5); } else { WriteValue(Convert.ToDouble(value, CultureInfo.InvariantCulture)); } break; case JsonToken.String: WriteValue(value?.ToString()); break; case JsonToken.Boolean: ValidationUtils.ArgumentNotNull(value, "value"); WriteValue(Convert.ToBoolean(value, CultureInfo.InvariantCulture)); break; case JsonToken.Null: WriteNull(); break; case JsonToken.Undefined: WriteUndefined(); break; case JsonToken.EndObject: WriteEndObject(); break; case JsonToken.EndArray: WriteEndArray(); break; case JsonToken.EndConstructor: WriteEndConstructor(); break; case JsonToken.Date: ValidationUtils.ArgumentNotNull(value, "value"); if (value is DateTimeOffset value6) { WriteValue(value6); } else { WriteValue(Convert.ToDateTime(value, CultureInfo.InvariantCulture)); } break; case JsonToken.Raw: WriteRawValue(value?.ToString()); break; case JsonToken.Bytes: ValidationUtils.ArgumentNotNull(value, "value"); if (value is Guid value2) { WriteValue(value2); } else { WriteValue((byte[])value); } break; default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("token", token, "Unexpected token type."); case JsonToken.None: break; } } public void WriteToken(JsonToken token) { WriteToken(token, null); } internal virtual void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments) { int num = CalculateWriteTokenInitialDepth(reader); do { if (writeDateConstructorAsDate && reader.TokenType == JsonToken.StartConstructor && string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { WriteConstructorDate(reader); } else if (writeComments || reader.TokenType != JsonToken.Comment) { WriteToken(reader.TokenType, reader.Value); } } while (num - 1 < reader.Depth - (JsonTokenUtils.IsEndToken(reader.TokenType) ? 1 : 0) && writeChildren && reader.Read()); if (IsWriteTokenIncomplete(reader, writeChildren, num)) { throw JsonWriterException.Create(this, "Unexpected end when reading token.", null); } } private bool IsWriteTokenIncomplete(JsonReader reader, bool writeChildren, int initialDepth) { int num = CalculateWriteTokenFinalDepth(reader); if (initialDepth >= num) { if (writeChildren && initialDepth == num) { return JsonTokenUtils.IsStartToken(reader.TokenType); } return false; } return true; } private int CalculateWriteTokenInitialDepth(JsonReader reader) { JsonToken tokenType = reader.TokenType; if (tokenType == JsonToken.None) { return -1; } if (!JsonTokenUtils.IsStartToken(tokenType)) { return reader.Depth + 1; } return reader.Depth; } private int CalculateWriteTokenFinalDepth(JsonReader reader) { JsonToken tokenType = reader.TokenType; if (tokenType == JsonToken.None) { return -1; } if (!JsonTokenUtils.IsEndToken(tokenType)) { return reader.Depth; } return reader.Depth - 1; } private void WriteConstructorDate(JsonReader reader) { if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime dateTime, out string errorMessage)) { throw JsonWriterException.Create(this, errorMessage, null); } WriteValue(dateTime); } private void WriteEnd(JsonContainerType type) { switch (type) { case JsonContainerType.Object: WriteEndObject(); break; case JsonContainerType.Array: WriteEndArray(); break; case JsonContainerType.Constructor: WriteEndConstructor(); break; default: throw JsonWriterException.Create(this, "Unexpected type when writing end: " + type, null); } } private void AutoCompleteAll() { while (Top > 0) { WriteEnd(); } } private JsonToken GetCloseTokenForType(JsonContainerType type) { return type switch { JsonContainerType.Object => JsonToken.EndObject, JsonContainerType.Array => JsonToken.EndArray, JsonContainerType.Constructor => JsonToken.EndConstructor, _ => throw JsonWriterException.Create(this, "No close token for type: " + type, null), }; } private void AutoCompleteClose(JsonContainerType type) { int num = CalculateLevelsToComplete(type); for (int i = 0; i < num; i++) { JsonToken closeTokenForType = GetCloseTokenForType(Pop()); if (_currentState == State.Property) { WriteNull(); } if (_formatting == Formatting.Indented && _currentState != State.ObjectStart && _currentState != State.ArrayStart) { WriteIndent(); } WriteEnd(closeTokenForType); UpdateCurrentState(); } } private int CalculateLevelsToComplete(JsonContainerType type) { int num = 0; if (_currentPosition.Type == type) { num = 1; } else { int num2 = Top - 2; for (int num3 = num2; num3 >= 0; num3--) { int index = num2 - num3; if (_stack[index].Type == type) { num = num3 + 2; break; } } } if (num == 0) { throw JsonWriterException.Create(this, "No token to close.", null); } return num; } private void UpdateCurrentState() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Array; break; case JsonContainerType.None: _currentState = State.Start; break; default: throw JsonWriterException.Create(this, "Unknown JsonType: " + jsonContainerType, null); } } protected virtual void WriteEnd(JsonToken token) { } protected virtual void WriteIndent() { } protected virtual void WriteValueDelimiter() { } protected virtual void WriteIndentSpace() { } internal void AutoComplete(JsonToken tokenBeingWritten) { State state = StateArray[(int)tokenBeingWritten][(int)_currentState]; if (state == State.Error) { throw JsonWriterException.Create(this, "Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), _currentState.ToString()), null); } if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) && tokenBeingWritten != JsonToken.Comment) { WriteValueDelimiter(); } if (_formatting == Formatting.Indented) { if (_currentState == State.Property) { WriteIndentSpace(); } if (_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.Constructor || _currentState == State.ConstructorStart || (tokenBeingWritten == JsonToken.PropertyName && _currentState != 0)) { WriteIndent(); } } _currentState = state; } public virtual void WriteNull() { InternalWriteValue(JsonToken.Null); } public virtual void WriteUndefined() { InternalWriteValue(JsonToken.Undefined); } public virtual void WriteRaw(string? json) { InternalWriteRaw(); } public virtual void WriteRawValue(string? json) { UpdateScopeWithFinishedValue(); AutoComplete(JsonToken.Undefined); WriteRaw(json); } public virtual void WriteValue(string? value) { InternalWriteValue(JsonToken.String); } public virtual void WriteValue(int value) { InternalWriteValue(JsonToken.Integer); } [CLSCompliant(false)] public virtual void WriteValue(uint value) { InternalWriteValue(JsonToken.Integer); } public virtual void WriteValue(long value) { InternalWriteValue(JsonToken.Integer); } [CLSCompliant(false)] public virtual void WriteValue(ulong value) { InternalWriteValue(JsonToken.Integer); } public virtual void WriteValue(float value) { InternalWriteValue(JsonToken.Float); } public virtual void WriteValue(double value) { InternalWriteValue(JsonToken.Float); } public virtual void WriteValue(bool value) { InternalWriteValue(JsonToken.Boolean); } public virtual void WriteValue(short value) { InternalWriteValue(JsonToken.Integer); } [CLSCompliant(false)] public virtual void WriteValue(ushort value) { InternalWriteValue(JsonToken.Integer); } public virtual void WriteValue(char value) { InternalWriteValue(JsonToken.String); } public virtual void WriteValue(byte value) { InternalWriteValue(JsonToken.Integer); } [CLSCompliant(false)] public virtual void WriteValue(sbyte value) { InternalWriteValue(JsonToken.Integer); } public virtual void WriteValue(decimal value) { InternalWriteValue(JsonToken.Float); } public virtual void WriteValue(DateTime value) { InternalWriteValue(JsonToken.Date); } public virtual void WriteValue(DateTimeOffset value) { InternalWriteValue(JsonToken.Date); } public virtual void WriteValue(Guid value) { InternalWriteValue(JsonToken.String); } public virtual void WriteValue(TimeSpan value) { InternalWriteValue(JsonToken.String); } public virtual void WriteValue(int? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } [CLSCompliant(false)] public virtual void WriteValue(uint? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(long? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } [CLSCompliant(false)] public virtual void WriteValue(ulong? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(float? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(double? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(bool? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(short? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } [CLSCompliant(false)] public virtual void WriteValue(ushort? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(char? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(byte? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } [CLSCompliant(false)] public virtual void WriteValue(sbyte? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(decimal? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(DateTime? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(DateTimeOffset? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(Guid? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(TimeSpan? value) { if (!value.HasValue) { WriteNull(); } else { WriteValue(value.GetValueOrDefault()); } } public virtual void WriteValue(byte[]? value) { if (value == null) { WriteNull(); } else { InternalWriteValue(JsonToken.Bytes); } } public virtual void WriteValue(Uri? value) { if (value == null) { WriteNull(); } else { InternalWriteValue(JsonToken.String); } } public virtual void WriteValue(object? value) { if (value == null) { WriteNull(); return; } if (value is BigInteger) { throw CreateUnsupportedTypeException(this, value); } WriteValue(this, ConvertUtils.GetTypeCode(value.GetType()), value); } public virtual void WriteComment(string? text) { InternalWriteComment(); } public virtual void WriteWhitespace(string ws) { InternalWriteWhitespace(ws); } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } internal static void WriteValue(JsonWriter writer, PrimitiveTypeCode typeCode, object value) { while (true) { switch (typeCode) { case PrimitiveTypeCode.Char: writer.WriteValue((char)value); return; case PrimitiveTypeCode.CharNullable: writer.WriteValue((value == null) ? null : new char?((char)value)); return; case PrimitiveTypeCode.Boolean: writer.WriteValue((bool)value); return; case PrimitiveTypeCode.BooleanNullable: writer.WriteValue((value == null) ? null : new bool?((bool)value)); return; case PrimitiveTypeCode.SByte: writer.WriteValue((sbyte)value); return; case PrimitiveTypeCode.SByteNullable: writer.WriteValue((value == null) ? null : new sbyte?((sbyte)value)); return; case PrimitiveTypeCode.Int16: writer.WriteValue((short)value); return; case PrimitiveTypeCode.Int16Nullable: writer.WriteValue((value == null) ? null : new short?((short)value)); return; case PrimitiveTypeCode.UInt16: writer.WriteValue((ushort)value); return; case PrimitiveTypeCode.UInt16Nullable: writer.WriteValue((value == null) ? null : new ushort?((ushort)value)); return; case PrimitiveTypeCode.Int32: writer.WriteValue((int)value); return; case PrimitiveTypeCode.Int32Nullable: writer.WriteValue((value == null) ? null : new int?((int)value)); return; case PrimitiveTypeCode.Byte: writer.WriteValue((byte)value); return; case PrimitiveTypeCode.ByteNullable: writer.WriteValue((value == null) ? null : new byte?((byte)value)); return; case PrimitiveTypeCode.UInt32: writer.WriteValue((uint)value); return; case PrimitiveTypeCode.UInt32Nullable: writer.WriteValue((value == null) ? null : new uint?((uint)value)); return; case PrimitiveTypeCode.Int64: writer.WriteValue((long)value); return; case PrimitiveTypeCode.Int64Nullable: writer.WriteValue((value == null) ? null : new long?((long)value)); return; case PrimitiveTypeCode.UInt64: writer.WriteValue((ulong)value); return; case PrimitiveTypeCode.UInt64Nullable: writer.WriteValue((value == null) ? null : new ulong?((ulong)value)); return; case PrimitiveTypeCode.Single: writer.WriteValue((float)value); return; case PrimitiveTypeCode.SingleNullable: writer.WriteValue((value == null) ? null : new float?((float)value)); return; case PrimitiveTypeCode.Double: writer.WriteValue((double)value); return; case PrimitiveTypeCode.DoubleNullable: writer.WriteValue((value == null) ? null : new double?((double)value)); return; case PrimitiveTypeCode.DateTime: writer.WriteValue((DateTime)value); return; case PrimitiveTypeCode.DateTimeNullable: writer.WriteValue((value == null) ? null : new DateTime?((DateTime)value)); return; case PrimitiveTypeCode.DateTimeOffset: writer.WriteValue((DateTimeOffset)value); return; case PrimitiveTypeCode.DateTimeOffsetNullable: writer.WriteValue((value == null) ? null : new DateTimeOffset?((DateTimeOffset)value)); return; case PrimitiveTypeCode.Decimal: writer.WriteValue((decimal)value); return; case PrimitiveTypeCode.DecimalNullable: writer.WriteValue((value == null) ? null : new decimal?((decimal)value)); return; case PrimitiveTypeCode.Guid: writer.WriteValue((Guid)value); return; case PrimitiveTypeCode.GuidNullable: writer.WriteValue((value == null) ? null : new Guid?((Guid)value)); return; case PrimitiveTypeCode.TimeSpan: writer.WriteValue((TimeSpan)value); return; case PrimitiveTypeCode.TimeSpanNullable: writer.WriteValue((value == null) ? null : new TimeSpan?((TimeSpan)value)); return; case PrimitiveTypeCode.BigInteger: writer.WriteValue((BigInteger)value); return; case PrimitiveTypeCode.BigIntegerNullable: writer.WriteValue((value == null) ? null : new BigInteger?((BigInteger)value)); return; case PrimitiveTypeCode.Uri: writer.WriteValue((Uri)value); return; case PrimitiveTypeCode.String: writer.WriteValue((string)value); return; case PrimitiveTypeCode.Bytes: writer.WriteValue((byte[])value); return; case PrimitiveTypeCode.DBNull: writer.WriteNull(); return; } if (value is IConvertible convertible) { ResolveConvertibleValue(convertible, out typeCode, out value); continue; } if (value == null) { writer.WriteNull(); return; } throw CreateUnsupportedTypeException(writer, value); } } private static void ResolveConvertibleValue(IConvertible convertible, out PrimitiveTypeCode typeCode, out object value) { TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertible); typeCode = ((typeInformation.TypeCode == PrimitiveTypeCode.Object) ? PrimitiveTypeCode.String : typeInformation.TypeCode); Type conversionType = ((typeInformation.TypeCode == PrimitiveTypeCode.Object) ? typeof(string) : typeInformation.Type); value = convertible.ToType(conversionType, CultureInfo.InvariantCulture); } private static JsonWriterException CreateUnsupportedTypeException(JsonWriter writer, object value) { return JsonWriterException.Create(writer, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null); } protected void SetWriteState(JsonToken token, object value) { switch (token) { case JsonToken.StartObject: InternalWriteStart(token, JsonContainerType.Object); break; case JsonToken.StartArray: InternalWriteStart(token, JsonContainerType.Array); break; case JsonToken.StartConstructor: InternalWriteStart(token, JsonContainerType.Constructor); break; case JsonToken.PropertyName: if (!(value is string name)) { throw new ArgumentException("A name is required when setting property name state.", "value"); } InternalWritePropertyName(name); break; case JsonToken.Comment: InternalWriteComment(); break; case JsonToken.Raw: InternalWriteRaw(); break; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: InternalWriteValue(token); break; case JsonToken.EndObject: InternalWriteEnd(JsonContainerType.Object); break; case JsonToken.EndArray: InternalWriteEnd(JsonContainerType.Array); break; case JsonToken.EndConstructor: InternalWriteEnd(JsonContainerType.Constructor); break; default: throw new ArgumentOutOfRangeException("token"); } } internal void InternalWriteEnd(JsonContainerType container) { AutoCompleteClose(container); } internal void InternalWritePropertyName(string name) { _currentPosition.PropertyName = name; AutoComplete(JsonToken.PropertyName); } internal void InternalWriteRaw() { } internal void InternalWriteStart(JsonToken token, JsonContainerType container) { UpdateScopeWithFinishedValue(); AutoComplete(token); Push(container); } internal void InternalWriteValue(JsonToken token) { UpdateScopeWithFinishedValue(); AutoComplete(token); } internal void InternalWriteWhitespace(string ws) { if (ws != null && !StringUtils.IsWhiteSpace(ws)) { throw JsonWriterException.Create(this, "Only white space characters should be used.", null); } } internal void InternalWriteComment() { AutoComplete(JsonToken.Comment); } } [Serializable] internal class JsonWriterException : JsonException { public string? Path { get; } public JsonWriterException() { } public JsonWriterException(string message) : base(message) { } public JsonWriterException(string message, Exception innerException) : base(message, innerException) { } public JsonWriterException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonWriterException(string message, string path, Exception? innerException) : base(message, innerException) { Path = path; } internal static JsonWriterException Create(JsonWriter writer, string message, Exception? ex) { return Create(writer.ContainerPath, message, ex); } internal static JsonWriterException Create(string path, string message, Exception? ex) { message = JsonPosition.FormatMessage(null, path, message); return new JsonWriterException(message, path, ex); } } internal enum MemberSerialization { OptOut, OptIn, Fields } internal enum MetadataPropertyHandling { Default, ReadAhead, Ignore } internal enum MissingMemberHandling { Ignore, Error } internal enum NullValueHandling { Include, Ignore } internal enum ObjectCreationHandling { Auto, Reuse, Replace } [Flags] internal enum PreserveReferencesHandling { None = 0, Objects = 1, Arrays = 2, All = 3 } internal enum ReferenceLoopHandling { Error, Ignore, Serialize } internal enum Required { Default, AllowNull, Always, DisallowNull } internal enum StringEscapeHandling { Default, EscapeNonAscii, EscapeHtml } internal enum TypeNameAssemblyFormatHandling { Simple, Full } [Flags] internal enum TypeNameHandling { None = 0, Objects = 1, Arrays = 2, All = 3, Auto = 4 } internal enum WriteState { Error, Closed, Object, Array, Constructor, Property, Start } } namespace Newtonsoft.Json.Utilities { internal static class AsyncUtils { public static readonly Task False = Task.FromResult(result: false); public static readonly Task True = Task.FromResult(result: true); internal static readonly Task CompletedTask = Task.Delay(0); internal static Task ToAsync(this bool value) { if (!value) { return False; } return True; } public static Task? CancelIfRequestedAsync(this CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return null; } return cancellationToken.FromCanceled(); } public static Task? CancelIfRequestedAsync(this CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return null; } return cancellationToken.FromCanceled(); } public static Task FromCanceled(this CancellationToken cancellationToken) { return new Task(delegate { }, cancellationToken); } public static Task FromCanceled(this CancellationToken cancellationToken) { return new Task(() => default(T), cancellationToken); } public static Task WriteAsync(this TextWriter writer, char value, CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return writer.WriteAsync(value); } return cancellationToken.FromCanceled(); } public static Task WriteAsync(this TextWriter writer, string? value, CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return writer.WriteAsync(value); } return cancellationToken.FromCanceled(); } public static Task WriteAsync(this TextWriter writer, char[] value, int start, int count, CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return writer.WriteAsync(value, start, count); } return cancellationToken.FromCanceled(); } public static Task ReadAsync(this TextReader reader, char[] buffer, int index, int count, CancellationToken cancellationToken) { if (!cancellationToken.IsCancellationRequested) { return reader.ReadAsync(buffer, index, count); } return cancellationToken.FromCanceled(); } public static bool IsCompletedSuccessfully(this Task task) { return task.Status == TaskStatus.RanToCompletion; } } internal class Base64Encoder { private const int Base64LineSize = 76; private const int LineSizeInBytes = 57; private readonly char[] _charsLine = new char[76]; private readonly TextWriter _writer; private byte[]? _leftOverBytes; private int _leftOverBytesCount; public Base64Encoder(TextWriter writer) { ValidationUtils.ArgumentNotNull(writer, "writer"); _writer = writer; } private void ValidateEncode(byte[] buffer, int index, int count) { if (buffer == null) { throw new ArgumentNullException("buffer"); } if (index < 0) { throw new ArgumentOutOfRangeException("index"); } if (count < 0) { throw new ArgumentOutOfRangeException("count"); } if (count > buffer.Length - index) { throw new ArgumentOutOfRangeException("count"); } } public void Encode(byte[] buffer, int index, int count) { ValidateEncode(buffer, index, count); if (_leftOverBytesCount > 0) { if (FulfillFromLeftover(buffer, index, ref count)) { return; } int count2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0); WriteChars(_charsLine, 0, count2); } StoreLeftOverBytes(buffer, index, ref count); int num = index + count; int num2 = 57; while (index < num) { if (index + num2 > num) { num2 = num - index; } int count3 = Convert.ToBase64CharArray(buffer, index, num2, _charsLine, 0); WriteChars(_charsLine, 0, count3); index += num2; } } private void StoreLeftOverBytes(byte[] buffer, int index, ref int count) { int num = count % 3; if (num > 0) { count -= num; if (_leftOverBytes == null) { _leftOverBytes = new byte[3]; } for (int i = 0; i < num; i++) { _leftOverBytes[i] = buffer[index + count + i]; } } _leftOverBytesCount = num; } private bool FulfillFromLeftover(byte[] buffer, int index, ref int count) { int leftOverBytesCount = _leftOverBytesCount; while (leftOverBytesCount < 3 && count > 0) { _leftOverBytes[leftOverBytesCount++] = buffer[index++]; count--; } if (count == 0 && leftOverBytesCount < 3) { _leftOverBytesCount = leftOverBytesCount; return true; } return false; } public void Flush() { if (_leftOverBytesCount > 0) { int count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0); WriteChars(_charsLine, 0, count); _leftOverBytesCount = 0; } } private void WriteChars(char[] chars, int index, int count) { _writer.Write(chars, index, count); } public async Task EncodeAsync(byte[] buffer, int index, int count, CancellationToken cancellationToken) { ValidateEncode(buffer, index, count); if (_leftOverBytesCount > 0) { if (FulfillFromLeftover(buffer, index, ref count)) { return; } int count2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0); await WriteCharsAsync(_charsLine, 0, count2, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } StoreLeftOverBytes(buffer, index, ref count); int num4 = index + count; int length = 57; while (index < num4) { if (index + length > num4) { length = num4 - index; } int count3 = Convert.ToBase64CharArray(buffer, index, length, _charsLine, 0); await WriteCharsAsync(_charsLine, 0, count3, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); index += length; } } private Task WriteCharsAsync(char[] chars, int index, int count, CancellationToken cancellationToken) { return _writer.WriteAsync(chars, index, count, cancellationToken); } public Task FlushAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } if (_leftOverBytesCount > 0) { int count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0); _leftOverBytesCount = 0; return WriteCharsAsync(_charsLine, 0, count, cancellationToken); } return AsyncUtils.CompletedTask; } } internal class BidirectionalDictionary where TFirst : notnull where TSecond : notnull { private readonly IDictionary _firstToSecond; private readonly IDictionary _secondToFirst; private readonly string _duplicateFirstErrorMessage; private readonly string _duplicateSecondErrorMessage; public BidirectionalDictionary() : this((IEqualityComparer)EqualityComparer.Default, (IEqualityComparer)EqualityComparer.Default) { } public BidirectionalDictionary(IEqualityComparer firstEqualityComparer, IEqualityComparer secondEqualityComparer) : this(firstEqualityComparer, secondEqualityComparer, "Duplicate item already exists for '{0}'.", "Duplicate item already exists for '{0}'.") { } public BidirectionalDictionary(IEqualityComparer firstEqualityComparer, IEqualityComparer secondEqualityComparer, string duplicateFirstErrorMessage, string duplicateSecondErrorMessage) { _firstToSecond = new Dictionary(firstEqualityComparer); _secondToFirst = new Dictionary(secondEqualityComparer); _duplicateFirstErrorMessage = duplicateFirstErrorMessage; _duplicateSecondErrorMessage = duplicateSecondErrorMessage; } public void Set(TFirst first, TSecond second) { if (_firstToSecond.TryGetValue(first, out var value) && !value.Equals(second)) { throw new ArgumentException(_duplicateFirstErrorMessage.FormatWith(CultureInfo.InvariantCulture, first)); } if (_secondToFirst.TryGetValue(second, out var value2) && !value2.Equals(first)) { throw new ArgumentException(_duplicateSecondErrorMessage.FormatWith(CultureInfo.InvariantCulture, second)); } _firstToSecond.Add(first, second); _secondToFirst.Add(second, first); } public bool TryGetByFirst(TFirst first, [NotNullWhen(true)] out TSecond? second) { return _firstToSecond.TryGetValue(first, out second); } public bool TryGetBySecond(TSecond second, [NotNullWhen(true)] out TFirst? first) { return _secondToFirst.TryGetValue(second, out first); } } internal static class BoxedPrimitives { internal static readonly object BooleanTrue = true; internal static readonly object BooleanFalse = false; internal static readonly object Int32_M1 = -1; internal static readonly object Int32_0 = 0; internal static readonly object Int32_1 = 1; internal static readonly object Int32_2 = 2; internal static readonly object Int32_3 = 3; internal static readonly object Int32_4 = 4; internal static readonly object Int32_5 = 5; internal static readonly object Int32_6 = 6; internal static readonly object Int32_7 = 7; internal static readonly object Int32_8 = 8; internal static readonly object Int64_M1 = -1L; internal static readonly object Int64_0 = 0L; internal static readonly object Int64_1 = 1L; internal static readonly object Int64_2 = 2L; internal static readonly object Int64_3 = 3L; internal static readonly object Int64_4 = 4L; internal static readonly object Int64_5 = 5L; internal static readonly object Int64_6 = 6L; internal static readonly object Int64_7 = 7L; internal static readonly object Int64_8 = 8L; internal static readonly object DoubleNaN = double.NaN; internal static readonly object DoublePositiveInfinity = double.PositiveInfinity; internal static readonly object DoubleNegativeInfinity = double.NegativeInfinity; internal static readonly object DoubleZero = 0.0; internal static readonly object DoubleNegativeZero = -0.0; internal static object Get(bool value) { if (!value) { return BooleanFalse; } return BooleanTrue; } internal static object Get(int value) { return value switch { -1 => Int32_M1, 0 => Int32_0, 1 => Int32_1, 2 => Int32_2, 3 => Int32_3, 4 => Int32_4, 5 => Int32_5, 6 => Int32_6, 7 => Int32_7, 8 => Int32_8, _ => value, }; } internal static object Get(long value) { long num = value - -1; if ((ulong)num <= 9uL) { switch (num) { case 0L: return Int64_M1; case 1L: return Int64_0; case 2L: return Int64_1; case 3L: return Int64_2; case 4L: return Int64_3; case 5L: return Int64_4; case 6L: return Int64_5; case 7L: return Int64_6; case 8L: return Int64_7; case 9L: return Int64_8; } } return value; } internal static object Get(decimal value) { return value; } internal static object Get(double value) { if (value == 0.0) { if (!double.IsNegativeInfinity(1.0 / value)) { return DoubleZero; } return DoubleNegativeZero; } if (double.IsInfinity(value)) { if (!double.IsPositiveInfinity(value)) { return DoubleNegativeInfinity; } return DoublePositiveInfinity; } if (double.IsNaN(value)) { return DoubleNaN; } return value; } } internal static class CollectionUtils { private static class EmptyArrayContainer { public static readonly T[] Empty = new T[0]; } public static bool IsNullOrEmpty(ICollection collection) { if (collection != null) { return collection.Count == 0; } return true; } public static void AddRange(this IList initial, IEnumerable collection) { if (initial == null) { throw new ArgumentNullException("initial"); } if (collection == null) { return; } foreach (T item in collection) { initial.Add(item); } } public static bool IsDictionaryType(Type type) { ValidationUtils.ArgumentNotNull(type, "type"); if (typeof(IDictionary).IsAssignableFrom(type)) { return true; } if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IDictionary<, >))) { return true; } if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IReadOnlyDictionary<, >))) { return true; } return false; } public static ConstructorInfo? ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType) { Type constructorArgumentType = typeof(IList<>).MakeGenericType(collectionItemType); return ResolveEnumerableCollectionConstructor(collectionType, collectionItemType, constructorArgumentType); } public static ConstructorInfo? ResolveEnumerableCollectionConstructor(Type collectionType, Type collectionItemType, Type constructorArgumentType) { Type type = typeof(IEnumerable<>).MakeGenericType(collectionItemType); ConstructorInfo constructorInfo = null; ConstructorInfo[] constructors = collectionType.GetConstructors(BindingFlags.Instance | BindingFlags.Public); foreach (ConstructorInfo constructorInfo2 in constructors) { IList parameters = constructorInfo2.GetParameters(); if (parameters.Count == 1) { Type parameterType = parameters[0].ParameterType; if (type == parameterType) { constructorInfo = constructorInfo2; break; } if (constructorInfo == null && parameterType.IsAssignableFrom(constructorArgumentType)) { constructorInfo = constructorInfo2; } } } return constructorInfo; } public static bool AddDistinct(this IList list, T value) { return list.AddDistinct(value, EqualityComparer.Default); } public static bool AddDistinct(this IList list, T value, IEqualityComparer comparer) { if (list.ContainsValue(value, comparer)) { return false; } list.Add(value); return true; } public static bool ContainsValue(this IEnumerable source, TSource value, IEqualityComparer comparer) { if (comparer == null) { comparer = EqualityComparer.Default; } if (source == null) { throw new ArgumentNullException("source"); } foreach (TSource item in source) { if (comparer.Equals(item, value)) { return true; } } return false; } public static bool AddRangeDistinct(this IList list, IEnumerable values, IEqualityComparer comparer) { bool result = true; foreach (T value in values) { if (!list.AddDistinct(value, comparer)) { result = false; } } return result; } public static int IndexOf(this IEnumerable collection, Func predicate) { int num = 0; foreach (T item in collection) { if (predicate(item)) { return num; } num++; } return -1; } public static bool Contains(this List list, T value, IEqualityComparer comparer) { for (int i = 0; i < list.Count; i++) { if (comparer.Equals(value, list[i])) { return true; } } return false; } public static int IndexOfReference(this List list, T item) { for (int i = 0; i < list.Count; i++) { if ((object)item == (object)list[i]) { return i; } } return -1; } public static void FastReverse(this List list) { int num = 0; int num2 = list.Count - 1; while (num < num2) { T value = list[num]; list[num] = list[num2]; list[num2] = value; num++; num2--; } } private static IList GetDimensions(IList values, int dimensionsCount) { IList list = new List(); IList list2 = values; while (true) { list.Add(list2.Count); if (list.Count == dimensionsCount || list2.Count == 0 || !(list2[0] is IList list3)) { break; } list2 = list3; } return list; } private static void CopyFromJaggedToMultidimensionalArray(IList values, Array multidimensionalArray, int[] indices) { int num = indices.Length; if (num == multidimensionalArray.Rank) { multidimensionalArray.SetValue(JaggedArrayGetValue(values, indices), indices); return; } int length = multidimensionalArray.GetLength(num); if (((IList)JaggedArrayGetValue(values, indices)).Count != length) { throw new Exception("Cannot deserialize non-cubical array as multidimensional array."); } int[] array = new int[num + 1]; for (int i = 0; i < num; i++) { array[i] = indices[i]; } for (int j = 0; j < multidimensionalArray.GetLength(num); j++) { array[num] = j; CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, array); } } private static object JaggedArrayGetValue(IList values, int[] indices) { IList list = values; for (int i = 0; i < indices.Length; i++) { int index = indices[i]; if (i == indices.Length - 1) { return list[index]; } list = (IList)list[index]; } return list; } public static Array ToMultidimensionalArray(IList values, Type type, int rank) { IList dimensions = GetDimensions(values, rank); while (dimensions.Count < rank) { dimensions.Add(0); } Array array = Array.CreateInstance(type, dimensions.ToArray()); CopyFromJaggedToMultidimensionalArray(values, array, ArrayEmpty()); return array; } public static T[] ArrayEmpty() { return EmptyArrayContainer.Empty; } } internal interface IWrappedCollection : IList, ICollection, IEnumerable { object UnderlyingCollection { get; } } internal class CollectionWrapper : ICollection, IEnumerable, IEnumerable, IWrappedCollection, IList, ICollection { private readonly IList? _list; private readonly ICollection? _genericCollection; private object? _syncRoot; public virtual int Count { get { if (_genericCollection != null) { return _genericCollection.Count; } return _list.Count; } } public virtual bool IsReadOnly { get { if (_genericCollection != null) { return _genericCollection.IsReadOnly; } return _list.IsReadOnly; } } bool IList.IsFixedSize { get { if (_genericCollection != null) { return _genericCollection.IsReadOnly; } return _list.IsFixedSize; } } object? IList.this[int index] { get { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support indexer."); } return _list[index]; } set { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support indexer."); } VerifyValueType(value); _list[index] = (T)value; } } bool ICollection.IsSynchronized => false; object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), null); } return _syncRoot; } } public object UnderlyingCollection => ((object)_genericCollection) ?? ((object)_list); public CollectionWrapper(IList list) { ValidationUtils.ArgumentNotNull(list, "list"); if (list is ICollection genericCollection) { _genericCollection = genericCollection; } else { _list = list; } } public CollectionWrapper(ICollection list) { ValidationUtils.ArgumentNotNull(list, "list"); _genericCollection = list; } public virtual void Add(T item) { if (_genericCollection != null) { _genericCollection.Add(item); } else { _list.Add(item); } } public virtual void Clear() { if (_genericCollection != null) { _genericCollection.Clear(); } else { _list.Clear(); } } public virtual bool Contains(T item) { if (_genericCollection != null) { return _genericCollection.Contains(item); } return _list.Contains(item); } public virtual void CopyTo(T[] array, int arrayIndex) { if (_genericCollection != null) { _genericCollection.CopyTo(array, arrayIndex); } else { _list.CopyTo(array, arrayIndex); } } public virtual bool Remove(T item) { if (_genericCollection != null) { return _genericCollection.Remove(item); } bool num = _list.Contains(item); if (num) { _list.Remove(item); } return num; } public virtual IEnumerator GetEnumerator() { IEnumerable genericCollection = _genericCollection; return (genericCollection ?? _list.Cast()).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { IEnumerable genericCollection = _genericCollection; return (genericCollection ?? _list).GetEnumerator(); } int IList.Add(object? value) { VerifyValueType(value); Add((T)value); return Count - 1; } bool IList.Contains(object? value) { if (IsCompatibleObject(value)) { return Contains((T)value); } return false; } int IList.IndexOf(object? value) { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support IndexOf."); } if (IsCompatibleObject(value)) { return _list.IndexOf((T)value); } return -1; } void IList.RemoveAt(int index) { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support RemoveAt."); } _list.RemoveAt(index); } void IList.Insert(int index, object? value) { if (_genericCollection != null) { throw new InvalidOperationException("Wrapped ICollection does not support Insert."); } VerifyValueType(value); _list.Insert(index, (T)value); } void IList.Remove(object? value) { if (IsCompatibleObject(value)) { Remove((T)value); } } void ICollection.CopyTo(Array array, int arrayIndex) { CopyTo((T[])array, arrayIndex); } private static void VerifyValueType(object? value) { if (!IsCompatibleObject(value)) { throw new ArgumentException("The value '{0}' is not of type '{1}' and cannot be used in this generic collection.".FormatWith(CultureInfo.InvariantCulture, value, typeof(T)), "value"); } } private static bool IsCompatibleObject(object? value) { if (!(value is T) && (value != null || (typeof(T).IsValueType() && !ReflectionUtils.IsNullableType(typeof(T))))) { return false; } return true; } } internal enum PrimitiveTypeCode { Empty, Object, Char, CharNullable, Boolean, BooleanNullable, SByte, SByteNullable, Int16, Int16Nullable, UInt16, UInt16Nullable, Int32, Int32Nullable, Byte, ByteNullable, UInt32, UInt32Nullable, Int64, Int64Nullable, UInt64, UInt64Nullable, Single, SingleNullable, Double, DoubleNullable, DateTime, DateTimeNullable, DateTimeOffset, DateTimeOffsetNullable, Decimal, DecimalNullable, Guid, GuidNullable, TimeSpan, TimeSpanNullable, BigInteger, BigIntegerNullable, Uri, String, Bytes, DBNull } internal class TypeInformation { public Type Type { get; } public PrimitiveTypeCode TypeCode { get; } public TypeInformation(Type type, PrimitiveTypeCode typeCode) { Type = type; TypeCode = typeCode; } } internal enum ParseResult { None, Success, Overflow, Invalid } internal static class ConvertUtils { internal enum ConvertResult { Success, CannotConvertNull, NotInstantiableType, NoValidConversion } private static readonly Dictionary TypeCodeMap = new Dictionary { { typeof(char), PrimitiveTypeCode.Char }, { typeof(char?), PrimitiveTypeCode.CharNullable }, { typeof(bool), PrimitiveTypeCode.Boolean }, { typeof(bool?), PrimitiveTypeCode.BooleanNullable }, { typeof(sbyte), PrimitiveTypeCode.SByte }, { typeof(sbyte?), PrimitiveTypeCode.SByteNullable }, { typeof(short), PrimitiveTypeCode.Int16 }, { typeof(short?), PrimitiveTypeCode.Int16Nullable }, { typeof(ushort), PrimitiveTypeCode.UInt16 }, { typeof(ushort?), PrimitiveTypeCode.UInt16Nullable }, { typeof(int), PrimitiveTypeCode.Int32 }, { typeof(int?), PrimitiveTypeCode.Int32Nullable }, { typeof(byte), PrimitiveTypeCode.Byte }, { typeof(byte?), PrimitiveTypeCode.ByteNullable }, { typeof(uint), PrimitiveTypeCode.UInt32 }, { typeof(uint?), PrimitiveTypeCode.UInt32Nullable }, { typeof(long), PrimitiveTypeCode.Int64 }, { typeof(long?), PrimitiveTypeCode.Int64Nullable }, { typeof(ulong), PrimitiveTypeCode.UInt64 }, { typeof(ulong?), PrimitiveTypeCode.UInt64Nullable }, { typeof(float), PrimitiveTypeCode.Single }, { typeof(float?), PrimitiveTypeCode.SingleNullable }, { typeof(double), PrimitiveTypeCode.Double }, { typeof(double?), PrimitiveTypeCode.DoubleNullable }, { typeof(DateTime), PrimitiveTypeCode.DateTime }, { typeof(DateTime?), PrimitiveTypeCode.DateTimeNullable }, { typeof(DateTimeOffset), PrimitiveTypeCode.DateTimeOffset }, { typeof(DateTimeOffset?), PrimitiveTypeCode.DateTimeOffsetNullable }, { typeof(decimal), PrimitiveTypeCode.Decimal }, { typeof(decimal?), PrimitiveTypeCode.DecimalNullable }, { typeof(Guid), PrimitiveTypeCode.Guid }, { typeof(Guid?), PrimitiveTypeCode.GuidNullable }, { typeof(TimeSpan), PrimitiveTypeCode.TimeSpan }, { typeof(TimeSpan?), PrimitiveTypeCode.TimeSpanNullable }, { typeof(BigInteger), PrimitiveTypeCode.BigInteger }, { typeof(BigInteger?), PrimitiveTypeCode.BigIntegerNullable }, { typeof(Uri), PrimitiveTypeCode.Uri }, { typeof(string), PrimitiveTypeCode.String }, { typeof(byte[]), PrimitiveTypeCode.Bytes }, { typeof(DBNull), PrimitiveTypeCode.DBNull } }; private static readonly TypeInformation[] PrimitiveTypeCodes = new TypeInformation[19] { new TypeInformation(typeof(object), PrimitiveTypeCode.Empty), new TypeInformation(typeof(object), PrimitiveTypeCode.Object), new TypeInformation(typeof(object), PrimitiveTypeCode.DBNull), new TypeInformation(typeof(bool), PrimitiveTypeCode.Boolean), new TypeInformation(typeof(char), PrimitiveTypeCode.Char), new TypeInformation(typeof(sbyte), PrimitiveTypeCode.SByte), new TypeInformation(typeof(byte), PrimitiveTypeCode.Byte), new TypeInformation(typeof(short), PrimitiveTypeCode.Int16), new TypeInformation(typeof(ushort), PrimitiveTypeCode.UInt16), new TypeInformation(typeof(int), PrimitiveTypeCode.Int32), new TypeInformation(typeof(uint), PrimitiveTypeCode.UInt32), new TypeInformation(typeof(long), PrimitiveTypeCode.Int64), new TypeInformation(typeof(ulong), PrimitiveTypeCode.UInt64), new TypeInformation(typeof(float), PrimitiveTypeCode.Single), new TypeInformation(typeof(double), PrimitiveTypeCode.Double), new TypeInformation(typeof(decimal), PrimitiveTypeCode.Decimal), new TypeInformation(typeof(DateTime), PrimitiveTypeCode.DateTime), new TypeInformation(typeof(object), PrimitiveTypeCode.Empty), new TypeInformation(typeof(string), PrimitiveTypeCode.String) }; private static readonly ThreadSafeStore, Func?> CastConverters = new ThreadSafeStore, Func>(CreateCastConverter); public static PrimitiveTypeCode GetTypeCode(Type t) { bool isEnum; return GetTypeCode(t, out isEnum); } public static PrimitiveTypeCode GetTypeCode(Type t, out bool isEnum) { if (TypeCodeMap.TryGetValue(t, out var value)) { isEnum = false; return value; } if (t.IsEnum()) { isEnum = true; return GetTypeCode(Enum.GetUnderlyingType(t)); } if (ReflectionUtils.IsNullableType(t)) { Type underlyingType = Nullable.GetUnderlyingType(t); if (underlyingType.IsEnum()) { Type t2 = typeof(Nullable<>).MakeGenericType(Enum.GetUnderlyingType(underlyingType)); isEnum = true; return GetTypeCode(t2); } } isEnum = false; return PrimitiveTypeCode.Object; } public static TypeInformation GetTypeInformation(IConvertible convertable) { return PrimitiveTypeCodes[(int)convertable.GetTypeCode()]; } public static bool IsConvertible(Type t) { return typeof(IConvertible).IsAssignableFrom(t); } public static TimeSpan ParseTimeSpan(string input) { return TimeSpan.Parse(input, CultureInfo.InvariantCulture); } private static Func? CreateCastConverter(StructMultiKey t) { Type value = t.Value1; Type value2 = t.Value2; MethodInfo methodInfo = value2.GetMethod("op_Implicit", new Type[1] { value }) ?? value2.GetMethod("op_Explicit", new Type[1] { value }); if (methodInfo == null) { return null; } MethodCall call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodInfo); return (object? o) => call(null, o); } internal static BigInteger ToBigInteger(object value) { if (value is BigInteger) { return (BigInteger)value; } if (value is string value2) { return BigInteger.Parse(value2, CultureInfo.InvariantCulture); } if (value is float value3) { return new BigInteger(value3); } if (value is double value4) { return new BigInteger(value4); } if (value is decimal value5) { return new BigInteger(value5); } if (value is int value6) { return new BigInteger(value6); } if (value is long value7) { return new BigInteger(value7); } if (value is uint value8) { return new BigInteger(value8); } if (value is ulong value9) { return new BigInteger(value9); } if (value is byte[] value10) { return new BigInteger(value10); } throw new InvalidCastException("Cannot convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } public static object FromBigInteger(BigInteger i, Type targetType) { if (targetType == typeof(decimal)) { return (decimal)i; } if (targetType == typeof(double)) { return (double)i; } if (targetType == typeof(float)) { return (float)i; } if (targetType == typeof(ulong)) { return (ulong)i; } if (targetType == typeof(bool)) { return i != 0L; } try { return System.Convert.ChangeType((long)i, targetType, CultureInfo.InvariantCulture); } catch (Exception innerException) { throw new InvalidOperationException("Can not convert from BigInteger to {0}.".FormatWith(CultureInfo.InvariantCulture, targetType), innerException); } } public static object Convert(object initialValue, CultureInfo culture, Type targetType) { object value; return TryConvertInternal(initialValue, culture, targetType, out value) switch { ConvertResult.Success => value, ConvertResult.CannotConvertNull => throw new Exception("Can not convert null {0} into non-nullable {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType)), ConvertResult.NotInstantiableType => throw new ArgumentException("Target type {0} is not a value type or a non-abstract class.".FormatWith(CultureInfo.InvariantCulture, targetType), "targetType"), ConvertResult.NoValidConversion => throw new InvalidOperationException("Can not convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType)), _ => throw new InvalidOperationException("Unexpected conversion result."), }; } private static bool TryConvert(object? initialValue, CultureInfo culture, Type targetType, out object? value) { try { if (TryConvertInternal(initialValue, culture, targetType, out value) == ConvertResult.Success) { return true; } value = null; return false; } catch { value = null; return false; } } private static ConvertResult TryConvertInternal(object? initialValue, CultureInfo culture, Type targetType, out object? value) { if (initialValue == null) { throw new ArgumentNullException("initialValue"); } if (ReflectionUtils.IsNullableType(targetType)) { targetType = Nullable.GetUnderlyingType(targetType); } Type type = initialValue.GetType(); if (targetType == type) { value = initialValue; return ConvertResult.Success; } if (IsConvertible(initialValue.GetType()) && IsConvertible(targetType)) { if (targetType.IsEnum()) { if (initialValue is string) { value = Enum.Parse(targetType, initialValue.ToString(), ignoreCase: true); return ConvertResult.Success; } if (IsInteger(initialValue)) { value = Enum.ToObject(targetType, initialValue); return ConvertResult.Success; } } value = System.Convert.ChangeType(initialValue, targetType, culture); return ConvertResult.Success; } if (initialValue is DateTime dateTime && targetType == typeof(DateTimeOffset)) { value = new DateTimeOffset(dateTime); return ConvertResult.Success; } if (initialValue is byte[] b && targetType == typeof(Guid)) { value = new Guid(b); return ConvertResult.Success; } if (initialValue is Guid guid && targetType == typeof(byte[])) { value = guid.ToByteArray(); return ConvertResult.Success; } if (initialValue is string text) { if (targetType == typeof(Guid)) { value = new Guid(text); return ConvertResult.Success; } if (targetType == typeof(Uri)) { value = new Uri(text, UriKind.RelativeOrAbsolute); return ConvertResult.Success; } if (targetType == typeof(TimeSpan)) { value = ParseTimeSpan(text); return ConvertResult.Success; } if (targetType == typeof(byte[])) { value = System.Convert.FromBase64String(text); return ConvertResult.Success; } if (targetType == typeof(Version)) { if (VersionTryParse(text, out Version result)) { value = result; return ConvertResult.Success; } value = null; return ConvertResult.NoValidConversion; } if (typeof(Type).IsAssignableFrom(targetType)) { value = Type.GetType(text, throwOnError: true); return ConvertResult.Success; } } if (targetType == typeof(BigInteger)) { value = ToBigInteger(initialValue); return ConvertResult.Success; } if (initialValue is BigInteger i) { value = FromBigInteger(i, targetType); return ConvertResult.Success; } TypeConverter converter = TypeDescriptor.GetConverter(type); if (converter != null && converter.CanConvertTo(targetType)) { value = converter.ConvertTo(null, culture, initialValue, targetType); return ConvertResult.Success; } TypeConverter converter2 = TypeDescriptor.GetConverter(targetType); if (converter2 != null && converter2.CanConvertFrom(type)) { value = converter2.ConvertFrom(null, culture, initialValue); return ConvertResult.Success; } if (initialValue == DBNull.Value) { if (ReflectionUtils.IsNullable(targetType)) { value = EnsureTypeAssignable(null, type, targetType); return ConvertResult.Success; } value = null; return ConvertResult.CannotConvertNull; } if (targetType.IsInterface() || targetType.IsGenericTypeDefinition() || targetType.IsAbstract()) { value = null; return ConvertResult.NotInstantiableType; } value = null; return ConvertResult.NoValidConversion; } public static object? ConvertOrCast(object? initialValue, CultureInfo culture, Type targetType) { if (targetType == typeof(object)) { return initialValue; } if (initialValue == null && ReflectionUtils.IsNullable(targetType)) { return null; } if (TryConvert(initialValue, culture, targetType, out object value)) { return value; } return EnsureTypeAssignable(initialValue, ReflectionUtils.GetObjectType(initialValue), targetType); } private static object? EnsureTypeAssignable(object? value, Type initialType, Type targetType) { if (value != null) { Type type = value.GetType(); if (targetType.IsAssignableFrom(type)) { return value; } Func func = CastConverters.Get(new StructMultiKey(type, targetType)); if (func != null) { return func(value); } } else if (ReflectionUtils.IsNullable(targetType)) { return null; } throw new ArgumentException("Could not cast or convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, initialType?.ToString() ?? "{null}", targetType)); } public static bool VersionTryParse(string input, [NotNullWhen(true)] out Version? result) { return Version.TryParse(input, out result); } public static bool IsInteger(object value) { switch (GetTypeCode(value.GetType())) { case PrimitiveTypeCode.SByte: case PrimitiveTypeCode.Int16: case PrimitiveTypeCode.UInt16: case PrimitiveTypeCode.Int32: case PrimitiveTypeCode.Byte: case PrimitiveTypeCode.UInt32: case PrimitiveTypeCode.Int64: case PrimitiveTypeCode.UInt64: return true; default: return false; } } public static ParseResult Int32TryParse(char[] chars, int start, int length, out int value) { value = 0; if (length == 0) { return ParseResult.Invalid; } bool flag = chars[start] == '-'; if (flag) { if (length == 1) { return ParseResult.Invalid; } start++; length--; } int num = start + length; if (length > 10 || (length == 10 && chars[start] - 48 > 2)) { for (int i = start; i < num; i++) { int num2 = chars[i] - 48; if (num2 < 0 || num2 > 9) { return ParseResult.Invalid; } } return ParseResult.Overflow; } for (int j = start; j < num; j++) { int num3 = chars[j] - 48; if (num3 < 0 || num3 > 9) { return ParseResult.Invalid; } int num4 = 10 * value - num3; if (num4 > value) { for (j++; j < num; j++) { num3 = chars[j] - 48; if (num3 < 0 || num3 > 9) { return ParseResult.Invalid; } } return ParseResult.Overflow; } value = num4; } if (!flag) { if (value == int.MinValue) { return ParseResult.Overflow; } value = -value; } return ParseResult.Success; } public static ParseResult Int64TryParse(char[] chars, int start, int length, out long value) { value = 0L; if (length == 0) { return ParseResult.Invalid; } bool flag = chars[start] == '-'; if (flag) { if (length == 1) { return ParseResult.Invalid; } start++; length--; } int num = start + length; if (length > 19) { for (int i = start; i < num; i++) { int num2 = chars[i] - 48; if (num2 < 0 || num2 > 9) { return ParseResult.Invalid; } } return ParseResult.Overflow; } for (int j = start; j < num; j++) { int num3 = chars[j] - 48; if (num3 < 0 || num3 > 9) { return ParseResult.Invalid; } long num4 = 10 * value - num3; if (num4 > value) { for (j++; j < num; j++) { num3 = chars[j] - 48; if (num3 < 0 || num3 > 9) { return ParseResult.Invalid; } } return ParseResult.Overflow; } value = num4; } if (!flag) { if (value == long.MinValue) { return ParseResult.Overflow; } value = -value; } return ParseResult.Success; } public static ParseResult DecimalTryParse(char[] chars, int start, int length, out decimal value) { value = default(decimal); if (length == 0) { return ParseResult.Invalid; } bool flag = chars[start] == '-'; if (flag) { if (length == 1) { return ParseResult.Invalid; } start++; length--; } int i = start; int num = start + length; int num2 = num; int num3 = num; int num4 = 0; ulong num5 = 0uL; ulong num6 = 0uL; int num7 = 0; int num8 = 0; char? c = null; bool? flag2 = null; for (; i < num; i++) { char c2 = chars[i]; if (c2 == '.') { goto IL_0074; } if (c2 == 'E' || c2 == 'e') { goto IL_0091; } if (c2 < '0' || c2 > '9') { return ParseResult.Invalid; } if (i == start && c2 == '0') { i++; if (i != num) { c2 = chars[i]; if (c2 == '.') { goto IL_0074; } if (c2 != 'e' && c2 != 'E') { return ParseResult.Invalid; } goto IL_0091; } } if (num7 < 29) { if (num7 == 28) { bool? flag3 = flag2; bool valueOrDefault; if (!flag3.HasValue) { flag2 = num5 > 7922816251426433759L || (num5 == 7922816251426433759L && (num6 > 354395033 || (num6 == 354395033 && c2 > '5'))); bool? flag4 = flag2; valueOrDefault = flag4.GetValueOrDefault(); } else { valueOrDefault = flag3.GetValueOrDefault(); } if (valueOrDefault) { goto IL_01ff; } } if (num7 < 19) { num5 = num5 * 10 + (ulong)(c2 - 48); } else { num6 = num6 * 10 + (ulong)(c2 - 48); } num7++; continue; } goto IL_01ff; IL_0074: if (i == start) { return ParseResult.Invalid; } if (i + 1 == num) { return ParseResult.Invalid; } if (num2 != num) { return ParseResult.Invalid; } num2 = i + 1; continue; IL_01ff: if (!c.HasValue) { c = c2; } num8++; continue; IL_0091: if (i == start) { return ParseResult.Invalid; } if (i == num2) { return ParseResult.Invalid; } i++; if (i == num) { return ParseResult.Invalid; } if (num2 < num) { num3 = i - 1; } c2 = chars[i]; bool flag5 = false; switch (c2) { case '-': flag5 = true; i++; break; case '+': i++; break; } for (; i < num; i++) { c2 = chars[i]; if (c2 < '0' || c2 > '9') { return ParseResult.Invalid; } int num9 = 10 * num4 + (c2 - 48); if (num4 < num9) { num4 = num9; } } if (flag5) { num4 = -num4; } } num4 += num8; num4 -= num3 - num2; if (num7 <= 19) { value = num5; } else { value = (decimal)num5 / new decimal(1, 0, 0, isNegative: false, (byte)(num7 - 19)) + (decimal)num6; } if (num4 > 0) { num7 += num4; if (num7 > 29) { return ParseResult.Overflow; } if (num7 == 29) { if (num4 > 1) { value /= new decimal(1, 0, 0, isNegative: false, (byte)(num4 - 1)); if (value > 7922816251426433759354395033m) { return ParseResult.Overflow; } } else if (value == 7922816251426433759354395033m && c > '5') { return ParseResult.Overflow; } value *= 10m; } else { value /= new decimal(1, 0, 0, isNegative: false, (byte)num4); } } else { if (c >= '5' && num4 >= -28) { ++value; } if (num4 < 0) { if (num7 + num4 + 28 <= 0) { value = (flag ? 0m : 0m); return ParseResult.Success; } if (num4 >= -28) { value *= new decimal(1, 0, 0, isNegative: false, (byte)(-num4)); } else { value /= 10000000000000000000000000000m; value *= new decimal(1, 0, 0, isNegative: false, (byte)(-num4 - 28)); } } } if (flag) { value = -value; } return ParseResult.Success; } public static bool TryConvertGuid(string s, out Guid g) { return Guid.TryParseExact(s, "D", out g); } public static bool TryHexTextToInt(char[] text, int start, int end, out int value) { value = 0; for (int i = start; i < end; i++) { char c = text[i]; int num; if (c <= '9' && c >= '0') { num = c - 48; } else if (c <= 'F' && c >= 'A') { num = c - 55; } else { if (c > 'f' || c < 'a') { value = 0; return false; } num = c - 87; } value += num << (end - 1 - i) * 4; } return true; } } internal enum ParserTimeZone { Unspecified, Utc, LocalWestOfUtc, LocalEastOfUtc } internal struct DateTimeParser { public int Year; public int Month; public int Day; public int Hour; public int Minute; public int Second; public int Fraction; public int ZoneHour; public int ZoneMinute; public ParserTimeZone Zone; private char[] _text; private int _end; private static readonly int[] Power10; private static readonly int Lzyyyy; private static readonly int Lzyyyy_; private static readonly int Lzyyyy_MM; private static readonly int Lzyyyy_MM_; private static readonly int Lzyyyy_MM_dd; private static readonly int Lzyyyy_MM_ddT; private static readonly int LzHH; private static readonly int LzHH_; private static readonly int LzHH_mm; private static readonly int LzHH_mm_; private static readonly int LzHH_mm_ss; private static readonly int Lz_; private static readonly int Lz_zz; private const short MaxFractionDigits = 7; static DateTimeParser() { Power10 = new int[7] { -1, 10, 100, 1000, 10000, 100000, 1000000 }; Lzyyyy = "yyyy".Length; Lzyyyy_ = "yyyy-".Length; Lzyyyy_MM = "yyyy-MM".Length; Lzyyyy_MM_ = "yyyy-MM-".Length; Lzyyyy_MM_dd = "yyyy-MM-dd".Length; Lzyyyy_MM_ddT = "yyyy-MM-ddT".Length; LzHH = "HH".Length; LzHH_ = "HH:".Length; LzHH_mm = "HH:mm".Length; LzHH_mm_ = "HH:mm:".Length; LzHH_mm_ss = "HH:mm:ss".Length; Lz_ = "-".Length; Lz_zz = "-zz".Length; } public bool Parse(char[] text, int startIndex, int length) { _text = text; _end = startIndex + length; if (ParseDate(startIndex) && ParseChar(Lzyyyy_MM_dd + startIndex, 'T') && ParseTimeAndZoneAndWhitespace(Lzyyyy_MM_ddT + startIndex)) { return true; } return false; } private bool ParseDate(int start) { if (Parse4Digit(start, out Year) && 1 <= Year && ParseChar(start + Lzyyyy, '-') && Parse2Digit(start + Lzyyyy_, out Month) && 1 <= Month && Month <= 12 && ParseChar(start + Lzyyyy_MM, '-') && Parse2Digit(start + Lzyyyy_MM_, out Day) && 1 <= Day) { return Day <= DateTime.DaysInMonth(Year, Month); } return false; } private bool ParseTimeAndZoneAndWhitespace(int start) { if (ParseTime(ref start)) { return ParseZone(start); } return false; } private bool ParseTime(ref int start) { if (!Parse2Digit(start, out Hour) || Hour > 24 || !ParseChar(start + LzHH, ':') || !Parse2Digit(start + LzHH_, out Minute) || Minute >= 60 || !ParseChar(start + LzHH_mm, ':') || !Parse2Digit(start + LzHH_mm_, out Second) || Second >= 60 || (Hour == 24 && (Minute != 0 || Second != 0))) { return false; } start += LzHH_mm_ss; if (ParseChar(start, '.')) { Fraction = 0; int num = 0; while (++start < _end && num < 7) { int num2 = _text[start] - 48; if (num2 < 0 || num2 > 9) { break; } Fraction = Fraction * 10 + num2; num++; } if (num < 7) { if (num == 0) { return false; } Fraction *= Power10[7 - num]; } if (Hour == 24 && Fraction != 0) { return false; } } return true; } private bool ParseZone(int start) { if (start < _end) { char c = _text[start]; if (c == 'Z' || c == 'z') { Zone = ParserTimeZone.Utc; start++; } else { if (start + 2 < _end && Parse2Digit(start + Lz_, out ZoneHour) && ZoneHour <= 99) { switch (c) { case '-': Zone = ParserTimeZone.LocalWestOfUtc; start += Lz_zz; break; case '+': Zone = ParserTimeZone.LocalEastOfUtc; start += Lz_zz; break; } } if (start < _end) { if (ParseChar(start, ':')) { start++; if (start + 1 < _end && Parse2Digit(start, out ZoneMinute) && ZoneMinute <= 99) { start += 2; } } else if (start + 1 < _end && Parse2Digit(start, out ZoneMinute) && ZoneMinute <= 99) { start += 2; } } } } return start == _end; } private bool Parse4Digit(int start, out int num) { if (start + 3 < _end) { int num2 = _text[start] - 48; int num3 = _text[start + 1] - 48; int num4 = _text[start + 2] - 48; int num5 = _text[start + 3] - 48; if (0 <= num2 && num2 < 10 && 0 <= num3 && num3 < 10 && 0 <= num4 && num4 < 10 && 0 <= num5 && num5 < 10) { num = ((num2 * 10 + num3) * 10 + num4) * 10 + num5; return true; } } num = 0; return false; } private bool Parse2Digit(int start, out int num) { if (start + 1 < _end) { int num2 = _text[start] - 48; int num3 = _text[start + 1] - 48; if (0 <= num2 && num2 < 10 && 0 <= num3 && num3 < 10) { num = num2 * 10 + num3; return true; } } num = 0; return false; } private bool ParseChar(int start, char ch) { if (start < _end) { return _text[start] == ch; } return false; } } internal static class DateTimeUtils { internal static readonly long InitialJavaScriptDateTicks; private const string IsoDateFormat = "yyyy-MM-ddTHH:mm:ss.FFFFFFFK"; private const int DaysPer100Years = 36524; private const int DaysPer400Years = 146097; private const int DaysPer4Years = 1461; private const int DaysPerYear = 365; private const long TicksPerDay = 864000000000L; private static readonly int[] DaysToMonth365; private static readonly int[] DaysToMonth366; static DateTimeUtils() { InitialJavaScriptDateTicks = 621355968000000000L; DaysToMonth365 = new int[13] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; DaysToMonth366 = new int[13] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; } public static TimeSpan GetUtcOffset(this DateTime d) { return TimeZoneInfo.Local.GetUtcOffset(d); } public static XmlDateTimeSerializationMode ToSerializationMode(DateTimeKind kind) { return kind switch { DateTimeKind.Local => XmlDateTimeSerializationMode.Local, DateTimeKind.Unspecified => XmlDateTimeSerializationMode.Unspecified, DateTimeKind.Utc => XmlDateTimeSerializationMode.Utc, _ => throw MiscellaneousUtils.CreateArgumentOutOfRangeException("kind", kind, "Unexpected DateTimeKind value."), }; } internal static DateTime EnsureDateTime(DateTime value, DateTimeZoneHandling timeZone) { switch (timeZone) { case DateTimeZoneHandling.Local: value = SwitchToLocalTime(value); break; case DateTimeZoneHandling.Utc: value = SwitchToUtcTime(value); break; case DateTimeZoneHandling.Unspecified: value = new DateTime(value.Ticks, DateTimeKind.Unspecified); break; default: throw new ArgumentException("Invalid date time handling value."); case DateTimeZoneHandling.RoundtripKind: break; } return value; } private static DateTime SwitchToLocalTime(DateTime value) { return value.Kind switch { DateTimeKind.Unspecified => new DateTime(value.Ticks, DateTimeKind.Local), DateTimeKind.Utc => value.ToLocalTime(), DateTimeKind.Local => value, _ => value, }; } private static DateTime SwitchToUtcTime(DateTime value) { return value.Kind switch { DateTimeKind.Unspecified => new DateTime(value.Ticks, DateTimeKind.Utc), DateTimeKind.Utc => value, DateTimeKind.Local => value.ToUniversalTime(), _ => value, }; } private static long ToUniversalTicks(DateTime dateTime) { if (dateTime.Kind == DateTimeKind.Utc) { return dateTime.Ticks; } return ToUniversalTicks(dateTime, dateTime.GetUtcOffset()); } private static long ToUniversalTicks(DateTime dateTime, TimeSpan offset) { if (dateTime.Kind == DateTimeKind.Utc || dateTime == DateTime.MaxValue || dateTime == DateTime.MinValue) { return dateTime.Ticks; } long num = dateTime.Ticks - offset.Ticks; if (num > 3155378975999999999L) { return 3155378975999999999L; } if (num < 0) { return 0L; } return num; } internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, TimeSpan offset) { return UniversalTicksToJavaScriptTicks(ToUniversalTicks(dateTime, offset)); } internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime) { return ConvertDateTimeToJavaScriptTicks(dateTime, convertToUtc: true); } internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, bool convertToUtc) { return UniversalTicksToJavaScriptTicks(convertToUtc ? ToUniversalTicks(dateTime) : dateTime.Ticks); } private static long UniversalTicksToJavaScriptTicks(long universalTicks) { return (universalTicks - InitialJavaScriptDateTicks) / 10000; } internal static DateTime ConvertJavaScriptTicksToDateTime(long javaScriptTicks) { return new DateTime(javaScriptTicks * 10000 + InitialJavaScriptDateTicks, DateTimeKind.Utc); } internal static bool TryParseDateTimeIso(StringReference text, DateTimeZoneHandling dateTimeZoneHandling, out DateTime dt) { DateTimeParser dateTimeParser = default(DateTimeParser); if (!dateTimeParser.Parse(text.Chars, text.StartIndex, text.Length)) { dt = default(DateTime); return false; } DateTime dateTime = CreateDateTime(dateTimeParser); switch (dateTimeParser.Zone) { case ParserTimeZone.Utc: dateTime = new DateTime(dateTime.Ticks, DateTimeKind.Utc); break; case ParserTimeZone.LocalWestOfUtc: { TimeSpan timeSpan2 = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); long num = dateTime.Ticks + timeSpan2.Ticks; long num4 = num; DateTime minValue = DateTime.MaxValue; if (num4 <= minValue.Ticks) { dateTime = new DateTime(num, DateTimeKind.Utc).ToLocalTime(); break; } num += dateTime.GetUtcOffset().Ticks; long num5 = num; minValue = DateTime.MaxValue; if (num5 > minValue.Ticks) { minValue = DateTime.MaxValue; num = minValue.Ticks; } dateTime = new DateTime(num, DateTimeKind.Local); break; } case ParserTimeZone.LocalEastOfUtc: { TimeSpan timeSpan = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0); long num = dateTime.Ticks - timeSpan.Ticks; long num2 = num; DateTime minValue = DateTime.MinValue; if (num2 >= minValue.Ticks) { dateTime = new DateTime(num, DateTimeKind.Utc).ToLocalTime(); break; } num += dateTime.GetUtcOffset().Ticks; long num3 = num; minValue = DateTime.MinValue; if (num3 < minValue.Ticks) { minValue = DateTime.MinValue; num = minValue.Ticks; } dateTime = new DateTime(num, DateTimeKind.Local); break; } } dt = EnsureDateTime(dateTime, dateTimeZoneHandling); return true; } internal static bool TryParseDateTimeOffsetIso(StringReference text, out DateTimeOffset dt) { DateTimeParser dateTimeParser = default(DateTimeParser); if (!dateTimeParser.Parse(text.Chars, text.StartIndex, text.Length)) { dt = default(DateTimeOffset); return false; } DateTime dateTime = CreateDateTime(dateTimeParser); TimeSpan offset = dateTimeParser.Zone switch { ParserTimeZone.Utc => new TimeSpan(0L), ParserTimeZone.LocalWestOfUtc => new TimeSpan(-dateTimeParser.ZoneHour, -dateTimeParser.ZoneMinute, 0), ParserTimeZone.LocalEastOfUtc => new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0), _ => TimeZoneInfo.Local.GetUtcOffset(dateTime), }; long num = dateTime.Ticks - offset.Ticks; if (num < 0 || num > 3155378975999999999L) { dt = default(DateTimeOffset); return false; } dt = new DateTimeOffset(dateTime, offset); return true; } private static DateTime CreateDateTime(DateTimeParser dateTimeParser) { bool flag; if (dateTimeParser.Hour == 24) { flag = true; dateTimeParser.Hour = 0; } else { flag = false; } DateTime result = new DateTime(dateTimeParser.Year, dateTimeParser.Month, dateTimeParser.Day, dateTimeParser.Hour, dateTimeParser.Minute, dateTimeParser.Second).AddTicks(dateTimeParser.Fraction); if (flag) { result = result.AddDays(1.0); } return result; } internal static bool TryParseDateTime(StringReference s, DateTimeZoneHandling dateTimeZoneHandling, string? dateFormatString, CultureInfo culture, out DateTime dt) { if (s.Length > 0) { int startIndex = s.StartIndex; if (s[startIndex] == '/') { if (s.Length >= 9 && s.StartsWith("/Date(") && s.EndsWith(")/") && TryParseDateTimeMicrosoft(s, dateTimeZoneHandling, out dt)) { return true; } } else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[startIndex]) && s[startIndex + 10] == 'T' && TryParseDateTimeIso(s, dateTimeZoneHandling, out dt)) { return true; } if (!StringUtils.IsNullOrEmpty(dateFormatString) && TryParseDateTimeExact(s.ToString(), dateTimeZoneHandling, dateFormatString, culture, out dt)) { return true; } } dt = default(DateTime); return false; } internal static bool TryParseDateTime(string s, DateTimeZoneHandling dateTimeZoneHandling, string? dateFormatString, CultureInfo culture, out DateTime dt) { if (s.Length > 0) { if (s[0] == '/') { if (s.Length >= 9 && s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal) && TryParseDateTimeMicrosoft(new StringReference(s.ToCharArray(), 0, s.Length), dateTimeZoneHandling, out dt)) { return true; } } else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T' && DateTime.TryParseExact(s, "yyyy-MM-ddTHH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt)) { dt = EnsureDateTime(dt, dateTimeZoneHandling); return true; } if (!StringUtils.IsNullOrEmpty(dateFormatString) && TryParseDateTimeExact(s, dateTimeZoneHandling, dateFormatString, culture, out dt)) { return true; } } dt = default(DateTime); return false; } internal static bool TryParseDateTimeOffset(StringReference s, string? dateFormatString, CultureInfo culture, out DateTimeOffset dt) { if (s.Length > 0) { int startIndex = s.StartIndex; if (s[startIndex] == '/') { if (s.Length >= 9 && s.StartsWith("/Date(") && s.EndsWith(")/") && TryParseDateTimeOffsetMicrosoft(s, out dt)) { return true; } } else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[startIndex]) && s[startIndex + 10] == 'T' && TryParseDateTimeOffsetIso(s, out dt)) { return true; } if (!StringUtils.IsNullOrEmpty(dateFormatString) && TryParseDateTimeOffsetExact(s.ToString(), dateFormatString, culture, out dt)) { return true; } } dt = default(DateTimeOffset); return false; } internal static bool TryParseDateTimeOffset(string s, string? dateFormatString, CultureInfo culture, out DateTimeOffset dt) { if (s.Length > 0) { if (s[0] == '/') { if (s.Length >= 9 && s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal) && TryParseDateTimeOffsetMicrosoft(new StringReference(s.ToCharArray(), 0, s.Length), out dt)) { return true; } } else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T' && DateTimeOffset.TryParseExact(s, "yyyy-MM-ddTHH:mm:ss.FFFFFFFK", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out dt) && TryParseDateTimeOffsetIso(new StringReference(s.ToCharArray(), 0, s.Length), out dt)) { return true; } if (!StringUtils.IsNullOrEmpty(dateFormatString) && TryParseDateTimeOffsetExact(s, dateFormatString, culture, out dt)) { return true; } } dt = default(DateTimeOffset); return false; } private static bool TryParseMicrosoftDate(StringReference text, out long ticks, out TimeSpan offset, out DateTimeKind kind) { kind = DateTimeKind.Utc; int num = text.IndexOf('+', 7, text.Length - 8); if (num == -1) { num = text.IndexOf('-', 7, text.Length - 8); } if (num != -1) { kind = DateTimeKind.Local; if (!TryReadOffset(text, num + text.StartIndex, out offset)) { ticks = 0L; return false; } } else { offset = TimeSpan.Zero; num = text.Length - 2; } return ConvertUtils.Int64TryParse(text.Chars, 6 + text.StartIndex, num - 6, out ticks) == ParseResult.Success; } private static bool TryParseDateTimeMicrosoft(StringReference text, DateTimeZoneHandling dateTimeZoneHandling, out DateTime dt) { if (!TryParseMicrosoftDate(text, out var ticks, out var _, out var kind)) { dt = default(DateTime); return false; } DateTime dateTime = ConvertJavaScriptTicksToDateTime(ticks); switch (kind) { case DateTimeKind.Unspecified: dt = DateTime.SpecifyKind(dateTime.ToLocalTime(), DateTimeKind.Unspecified); break; case DateTimeKind.Local: dt = dateTime.ToLocalTime(); break; default: dt = dateTime; break; } dt = EnsureDateTime(dt, dateTimeZoneHandling); return true; } private static bool TryParseDateTimeExact(string text, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out DateTime dt) { if (DateTime.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out var result)) { result = EnsureDateTime(result, dateTimeZoneHandling); dt = result; return true; } dt = default(DateTime); return false; } private static bool TryParseDateTimeOffsetMicrosoft(StringReference text, out DateTimeOffset dt) { if (!TryParseMicrosoftDate(text, out var ticks, out var offset, out var _)) { dt = default(DateTime); return false; } dt = new DateTimeOffset(ConvertJavaScriptTicksToDateTime(ticks).Add(offset).Ticks, offset); return true; } private static bool TryParseDateTimeOffsetExact(string text, string dateFormatString, CultureInfo culture, out DateTimeOffset dt) { if (DateTimeOffset.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out var result)) { dt = result; return true; } dt = default(DateTimeOffset); return false; } private static bool TryReadOffset(StringReference offsetText, int startIndex, out TimeSpan offset) { bool flag = offsetText[startIndex] == '-'; if (ConvertUtils.Int32TryParse(offsetText.Chars, startIndex + 1, 2, out var value) != ParseResult.Success) { offset = default(TimeSpan); return false; } int value2 = 0; if (offsetText.Length - startIndex > 5 && ConvertUtils.Int32TryParse(offsetText.Chars, startIndex + 3, 2, out value2) != ParseResult.Success) { offset = default(TimeSpan); return false; } offset = TimeSpan.FromHours(value) + TimeSpan.FromMinutes(value2); if (flag) { offset = offset.Negate(); } return true; } internal static void WriteDateTimeString(TextWriter writer, DateTime value, DateFormatHandling format, string? formatString, CultureInfo culture) { if (StringUtils.IsNullOrEmpty(formatString)) { char[] array = new char[64]; int count = WriteDateTimeString(array, 0, value, null, value.Kind, format); writer.Write(array, 0, count); } else { writer.Write(value.ToString(formatString, culture)); } } internal static int WriteDateTimeString(char[] chars, int start, DateTime value, TimeSpan? offset, DateTimeKind kind, DateFormatHandling format) { int num = start; if (format == DateFormatHandling.MicrosoftDateFormat) { TimeSpan offset2 = offset ?? value.GetUtcOffset(); long num2 = ConvertDateTimeToJavaScriptTicks(value, offset2); "\\/Date(".CopyTo(0, chars, num, 7); num += 7; string text = num2.ToString(CultureInfo.InvariantCulture); text.CopyTo(0, chars, num, text.Length); num += text.Length; switch (kind) { case DateTimeKind.Unspecified: if (value != DateTime.MaxValue && value != DateTime.MinValue) { num = WriteDateTimeOffset(chars, num, offset2, format); } break; case DateTimeKind.Local: num = WriteDateTimeOffset(chars, num, offset2, format); break; } ")\\/".CopyTo(0, chars, num, 3); num += 3; } else { num = WriteDefaultIsoDate(chars, num, value); switch (kind) { case DateTimeKind.Local: num = WriteDateTimeOffset(chars, num, offset ?? value.GetUtcOffset(), format); break; case DateTimeKind.Utc: chars[num++] = 'Z'; break; } } return num; } internal static int WriteDefaultIsoDate(char[] chars, int start, DateTime dt) { int num = 19; GetDateValues(dt, out var year, out var month, out var day); CopyIntToCharArray(chars, start, year, 4); chars[start + 4] = '-'; CopyIntToCharArray(chars, start + 5, month, 2); chars[start + 7] = '-'; CopyIntToCharArray(chars, start + 8, day, 2); chars[start + 10] = 'T'; CopyIntToCharArray(chars, start + 11, dt.Hour, 2); chars[start + 13] = ':'; CopyIntToCharArray(chars, start + 14, dt.Minute, 2); chars[start + 16] = ':'; CopyIntToCharArray(chars, start + 17, dt.Second, 2); int num2 = (int)(dt.Ticks % 10000000); if (num2 != 0) { int num3 = 7; while (num2 % 10 == 0) { num3--; num2 /= 10; } chars[start + 19] = '.'; CopyIntToCharArray(chars, start + 20, num2, num3); num += num3 + 1; } return start + num; } private static void CopyIntToCharArray(char[] chars, int start, int value, int digits) { while (digits-- != 0) { chars[start + digits] = (char)(value % 10 + 48); value /= 10; } } internal static int WriteDateTimeOffset(char[] chars, int start, TimeSpan offset, DateFormatHandling format) { chars[start++] = ((offset.Ticks >= 0) ? '+' : '-'); int value = Math.Abs(offset.Hours); CopyIntToCharArray(chars, start, value, 2); start += 2; if (format == DateFormatHandling.IsoDateFormat) { chars[start++] = ':'; } int value2 = Math.Abs(offset.Minutes); CopyIntToCharArray(chars, start, value2, 2); start += 2; return start; } internal static void WriteDateTimeOffsetString(TextWriter writer, DateTimeOffset value, DateFormatHandling format, string? formatString, CultureInfo culture) { if (StringUtils.IsNullOrEmpty(formatString)) { char[] array = new char[64]; int count = WriteDateTimeString(array, 0, (format == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, format); writer.Write(array, 0, count); } else { writer.Write(value.ToString(formatString, culture)); } } private static void GetDateValues(DateTime td, out int year, out int month, out int day) { int num = (int)(td.Ticks / 864000000000L); int num2 = num / 146097; num -= num2 * 146097; int num3 = num / 36524; if (num3 == 4) { num3 = 3; } num -= num3 * 36524; int num4 = num / 1461; num -= num4 * 1461; int num5 = num / 365; if (num5 == 4) { num5 = 3; } year = num2 * 400 + num3 * 100 + num4 * 4 + num5 + 1; num -= num5 * 365; int[] array = ((num5 == 3 && (num4 != 24 || num3 == 3)) ? DaysToMonth366 : DaysToMonth365); int i; for (i = num >> 6; num >= array[i]; i++) { } month = i; day = num - array[i - 1] + 1; } } internal interface IWrappedDictionary : IDictionary, ICollection, IEnumerable { object UnderlyingDictionary { get; } } internal class DictionaryWrapper : IDictionary, ICollection>, IEnumerable>, IEnumerable, IWrappedDictionary, IDictionary, ICollection { private readonly struct DictionaryEnumerator : IDictionaryEnumerator, IEnumerator { private readonly IEnumerator> _e; public DictionaryEntry Entry => (DictionaryEntry)Current; public object Key => Entry.Key; public object? Value => Entry.Value; public object Current => new DictionaryEntry(_e.Current.Key, _e.Current.Value); public DictionaryEnumerator(IEnumerator> e) { ValidationUtils.ArgumentNotNull(e, "e"); _e = e; } public bool MoveNext() { return _e.MoveNext(); } public void Reset() { _e.Reset(); } } private readonly IDictionary? _dictionary; private readonly IDictionary? _genericDictionary; private readonly IReadOnlyDictionary? _readOnlyDictionary; private object? _syncRoot; internal IDictionary GenericDictionary => _genericDictionary; public ICollection Keys { get { if (_dictionary != null) { return _dictionary.Keys.Cast().ToList(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Keys.ToList(); } return GenericDictionary.Keys; } } public ICollection Values { get { if (_dictionary != null) { return _dictionary.Values.Cast().ToList(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Values.ToList(); } return GenericDictionary.Values; } } public TValue this[TKey key] { get { if (_dictionary != null) { return (TValue)_dictionary[key]; } if (_readOnlyDictionary != null) { return _readOnlyDictionary[key]; } return GenericDictionary[key]; } set { if (_dictionary != null) { _dictionary[key] = value; return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary[key] = value; } } public int Count { get { if (_dictionary != null) { return _dictionary.Count; } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Count; } return GenericDictionary.Count; } } public bool IsReadOnly { get { if (_dictionary != null) { return _dictionary.IsReadOnly; } if (_readOnlyDictionary != null) { return true; } return GenericDictionary.IsReadOnly; } } object? IDictionary.this[object key] { get { if (_dictionary != null) { return _dictionary[key]; } if (_readOnlyDictionary != null) { return _readOnlyDictionary[(TKey)key]; } return GenericDictionary[(TKey)key]; } set { if (_dictionary != null) { _dictionary[key] = value; return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary[(TKey)key] = (TValue)value; } } bool IDictionary.IsFixedSize { get { if (_genericDictionary != null) { return false; } if (_readOnlyDictionary != null) { return true; } return _dictionary.IsFixedSize; } } ICollection IDictionary.Keys { get { if (_genericDictionary != null) { return _genericDictionary.Keys.ToList(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Keys.ToList(); } return _dictionary.Keys; } } ICollection IDictionary.Values { get { if (_genericDictionary != null) { return _genericDictionary.Values.ToList(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Values.ToList(); } return _dictionary.Values; } } bool ICollection.IsSynchronized { get { if (_dictionary != null) { return _dictionary.IsSynchronized; } return false; } } object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), null); } return _syncRoot; } } public object UnderlyingDictionary { get { if (_dictionary != null) { return _dictionary; } if (_readOnlyDictionary != null) { return _readOnlyDictionary; } return GenericDictionary; } } public DictionaryWrapper(IDictionary dictionary) { ValidationUtils.ArgumentNotNull(dictionary, "dictionary"); _dictionary = dictionary; } public DictionaryWrapper(IDictionary dictionary) { ValidationUtils.ArgumentNotNull(dictionary, "dictionary"); _genericDictionary = dictionary; } public DictionaryWrapper(IReadOnlyDictionary dictionary) { ValidationUtils.ArgumentNotNull(dictionary, "dictionary"); _readOnlyDictionary = dictionary; } public void Add(TKey key, TValue value) { if (_dictionary != null) { _dictionary.Add(key, value); return; } if (_genericDictionary != null) { _genericDictionary.Add(key, value); return; } throw new NotSupportedException(); } public bool ContainsKey(TKey key) { if (_dictionary != null) { return _dictionary.Contains(key); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.ContainsKey(key); } return GenericDictionary.ContainsKey(key); } public bool Remove(TKey key) { if (_dictionary != null) { if (_dictionary.Contains(key)) { _dictionary.Remove(key); return true; } return false; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } return GenericDictionary.Remove(key); } public bool TryGetValue(TKey key, out TValue? value) { if (_dictionary != null) { if (!_dictionary.Contains(key)) { value = default(TValue); return false; } value = (TValue)_dictionary[key]; return true; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } return GenericDictionary.TryGetValue(key, out value); } public void Add(KeyValuePair item) { if (_dictionary != null) { ((IList)_dictionary).Add(item); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } _genericDictionary?.Add(item); } public void Clear() { if (_dictionary != null) { _dictionary.Clear(); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.Clear(); } public bool Contains(KeyValuePair item) { if (_dictionary != null) { return ((IList)_dictionary).Contains(item); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.Contains(item); } return GenericDictionary.Contains(item); } public void CopyTo(KeyValuePair[] array, int arrayIndex) { if (_dictionary != null) { foreach (DictionaryEntry item in _dictionary) { array[arrayIndex++] = new KeyValuePair((TKey)item.Key, (TValue)item.Value); } return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.CopyTo(array, arrayIndex); } public bool Remove(KeyValuePair item) { if (_dictionary != null) { if (_dictionary.Contains(item.Key)) { if (object.Equals(_dictionary[item.Key], item.Value)) { _dictionary.Remove(item.Key); return true; } return false; } return true; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } return GenericDictionary.Remove(item); } public IEnumerator> GetEnumerator() { if (_dictionary != null) { return (from DictionaryEntry de in _dictionary select new KeyValuePair((TKey)de.Key, (TValue)de.Value)).GetEnumerator(); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.GetEnumerator(); } return GenericDictionary.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void IDictionary.Add(object key, object? value) { if (_dictionary != null) { _dictionary.Add(key, value); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.Add((TKey)key, (TValue)value); } IDictionaryEnumerator IDictionary.GetEnumerator() { if (_dictionary != null) { return _dictionary.GetEnumerator(); } if (_readOnlyDictionary != null) { return new DictionaryEnumerator(_readOnlyDictionary.GetEnumerator()); } return new DictionaryEnumerator(GenericDictionary.GetEnumerator()); } bool IDictionary.Contains(object key) { if (_genericDictionary != null) { return _genericDictionary.ContainsKey((TKey)key); } if (_readOnlyDictionary != null) { return _readOnlyDictionary.ContainsKey((TKey)key); } return _dictionary.Contains(key); } public void Remove(object key) { if (_dictionary != null) { _dictionary.Remove(key); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.Remove((TKey)key); } void ICollection.CopyTo(Array array, int index) { if (_dictionary != null) { _dictionary.CopyTo(array, index); return; } if (_readOnlyDictionary != null) { throw new NotSupportedException(); } GenericDictionary.CopyTo((KeyValuePair[])array, index); } } internal class DynamicProxy { public virtual IEnumerable GetDynamicMemberNames(T instance) { return CollectionUtils.ArrayEmpty(); } public virtual bool TryBinaryOperation(T instance, BinaryOperationBinder binder, object arg, out object? result) { result = null; return false; } public virtual bool TryConvert(T instance, ConvertBinder binder, out object? result) { result = null; return false; } public virtual bool TryCreateInstance(T instance, CreateInstanceBinder binder, object[] args, out object? result) { result = null; return false; } public virtual bool TryDeleteIndex(T instance, DeleteIndexBinder binder, object[] indexes) { return false; } public virtual bool TryDeleteMember(T instance, DeleteMemberBinder binder) { return false; } public virtual bool TryGetIndex(T instance, GetIndexBinder binder, object[] indexes, out object? result) { result = null; return false; } public virtual bool TryGetMember(T instance, GetMemberBinder binder, out object? result) { result = null; return false; } public virtual bool TryInvoke(T instance, InvokeBinder binder, object[] args, out object? result) { result = null; return false; } public virtual bool TryInvokeMember(T instance, InvokeMemberBinder binder, object[] args, out object? result) { result = null; return false; } public virtual bool TrySetIndex(T instance, SetIndexBinder binder, object[] indexes, object value) { return false; } public virtual bool TrySetMember(T instance, SetMemberBinder binder, object value) { return false; } public virtual bool TryUnaryOperation(T instance, UnaryOperationBinder binder, out object? result) { result = null; return false; } } internal sealed class DynamicProxyMetaObject : DynamicMetaObject { private delegate DynamicMetaObject Fallback(DynamicMetaObject? errorSuggestion); private sealed class GetBinderAdapter : GetMemberBinder { internal GetBinderAdapter(InvokeMemberBinder binder) : base(binder.Name, binder.IgnoreCase) { } public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject? errorSuggestion) { throw new NotSupportedException(); } } private readonly DynamicProxy _proxy; private static Expression[] NoArgs => CollectionUtils.ArrayEmpty(); internal DynamicProxyMetaObject(Expression expression, T value, DynamicProxy proxy) : base(expression, BindingRestrictions.Empty, value) { _proxy = proxy; } private bool IsOverridden(string method) { return ReflectionUtils.IsMethodOverridden(_proxy.GetType(), typeof(DynamicProxy), method); } public override DynamicMetaObject BindGetMember(GetMemberBinder binder) { GetMemberBinder binder2 = binder; if (!IsOverridden("TryGetMember")) { return base.BindGetMember(binder2); } return CallMethodWithResult("TryGetMember", binder2, NoArgs, (DynamicMetaObject? e) => binder2.FallbackGetMember(this, e)); } public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value) { SetMemberBinder binder2 = binder; DynamicMetaObject value2 = value; if (!IsOverridden("TrySetMember")) { return base.BindSetMember(binder2, value2); } return CallMethodReturnLast("TrySetMember", binder2, GetArgs(value2), (DynamicMetaObject? e) => binder2.FallbackSetMember(this, value2, e)); } public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder) { DeleteMemberBinder binder2 = binder; if (!IsOverridden("TryDeleteMember")) { return base.BindDeleteMember(binder2); } return CallMethodNoResult("TryDeleteMember", binder2, NoArgs, (DynamicMetaObject? e) => binder2.FallbackDeleteMember(this, e)); } public override DynamicMetaObject BindConvert(ConvertBinder binder) { ConvertBinder binder2 = binder; if (!IsOverridden("TryConvert")) { return base.BindConvert(binder2); } return CallMethodWithResult("TryConvert", binder2, NoArgs, (DynamicMetaObject? e) => binder2.FallbackConvert(this, e)); } public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args) { InvokeMemberBinder binder2 = binder; DynamicMetaObject[] args2 = args; if (!IsOverridden("TryInvokeMember")) { return base.BindInvokeMember(binder2, args2); } Fallback fallback = (DynamicMetaObject? e) => binder2.FallbackInvokeMember(this, args2, e); return BuildCallMethodWithResult("TryInvokeMember", binder2, GetArgArray(args2), BuildCallMethodWithResult("TryGetMember", new GetBinderAdapter(binder2), NoArgs, fallback(null), (DynamicMetaObject? e) => binder2.FallbackInvoke(e, args2, null)), null); } public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args) { CreateInstanceBinder binder2 = binder; DynamicMetaObject[] args2 = args; if (!IsOverridden("TryCreateInstance")) { return base.BindCreateInstance(binder2, args2); } return CallMethodWithResult("TryCreateInstance", binder2, GetArgArray(args2), (DynamicMetaObject? e) => binder2.FallbackCreateInstance(this, args2, e)); } public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args) { InvokeBinder binder2 = binder; DynamicMetaObject[] args2 = args; if (!IsOverridden("TryInvoke")) { return base.BindInvoke(binder2, args2); } return CallMethodWithResult("TryInvoke", binder2, GetArgArray(args2), (DynamicMetaObject? e) => binder2.FallbackInvoke(this, args2, e)); } public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg) { BinaryOperationBinder binder2 = binder; DynamicMetaObject arg2 = arg; if (!IsOverridden("TryBinaryOperation")) { return base.BindBinaryOperation(binder2, arg2); } return CallMethodWithResult("TryBinaryOperation", binder2, GetArgs(arg2), (DynamicMetaObject? e) => binder2.FallbackBinaryOperation(this, arg2, e)); } public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder) { UnaryOperationBinder binder2 = binder; if (!IsOverridden("TryUnaryOperation")) { return base.BindUnaryOperation(binder2); } return CallMethodWithResult("TryUnaryOperation", binder2, NoArgs, (DynamicMetaObject? e) => binder2.FallbackUnaryOperation(this, e)); } public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes) { GetIndexBinder binder2 = binder; DynamicMetaObject[] indexes2 = indexes; if (!IsOverridden("TryGetIndex")) { return base.BindGetIndex(binder2, indexes2); } return CallMethodWithResult("TryGetIndex", binder2, GetArgArray(indexes2), (DynamicMetaObject? e) => binder2.FallbackGetIndex(this, indexes2, e)); } public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value) { SetIndexBinder binder2 = binder; DynamicMetaObject[] indexes2 = indexes; DynamicMetaObject value2 = value; if (!IsOverridden("TrySetIndex")) { return base.BindSetIndex(binder2, indexes2, value2); } return CallMethodReturnLast("TrySetIndex", binder2, GetArgArray(indexes2, value2), (DynamicMetaObject? e) => binder2.FallbackSetIndex(this, indexes2, value2, e)); } public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes) { DeleteIndexBinder binder2 = binder; DynamicMetaObject[] indexes2 = indexes; if (!IsOverridden("TryDeleteIndex")) { return base.BindDeleteIndex(binder2, indexes2); } return CallMethodNoResult("TryDeleteIndex", binder2, GetArgArray(indexes2), (DynamicMetaObject? e) => binder2.FallbackDeleteIndex(this, indexes2, e)); } private static IEnumerable GetArgs(params DynamicMetaObject[] args) { return args.Select(delegate(DynamicMetaObject arg) { Expression expression = arg.Expression; return (!expression.Type.IsValueType()) ? expression : System.Linq.Expressions.Expression.Convert(expression, typeof(object)); }); } private static Expression[] GetArgArray(DynamicMetaObject[] args) { return new NewArrayExpression[1] { System.Linq.Expressions.Expression.NewArrayInit(typeof(object), GetArgs(args)) }; } private static Expression[] GetArgArray(DynamicMetaObject[] args, DynamicMetaObject value) { Expression expression = value.Expression; return new Expression[2] { System.Linq.Expressions.Expression.NewArrayInit(typeof(object), GetArgs(args)), expression.Type.IsValueType() ? System.Linq.Expressions.Expression.Convert(expression, typeof(object)) : expression }; } private static ConstantExpression Constant(DynamicMetaObjectBinder binder) { Type type = binder.GetType(); while (!type.IsVisible()) { type = type.BaseType(); } return System.Linq.Expressions.Expression.Constant(binder, type); } private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, Fallback fallback, Fallback? fallbackInvoke = null) { DynamicMetaObject fallbackResult = fallback(null); return BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke); } private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, DynamicMetaObject fallbackResult, Fallback? fallbackInvoke) { ParameterExpression parameterExpression = System.Linq.Expressions.Expression.Parameter(typeof(object), null); IList list = new List(); list.Add(System.Linq.Expressions.Expression.Convert(base.Expression, typeof(T))); list.Add(Constant(binder)); list.AddRange(args); list.Add(parameterExpression); DynamicMetaObject dynamicMetaObject = new DynamicMetaObject(parameterExpression, BindingRestrictions.Empty); if (binder.ReturnType != typeof(object)) { dynamicMetaObject = new DynamicMetaObject(System.Linq.Expressions.Expression.Convert(dynamicMetaObject.Expression, binder.ReturnType), dynamicMetaObject.Restrictions); } if (fallbackInvoke != null) { dynamicMetaObject = fallbackInvoke(dynamicMetaObject); } return new DynamicMetaObject(System.Linq.Expressions.Expression.Block(new ParameterExpression[1] { parameterExpression }, System.Linq.Expressions.Expression.Condition(System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression.Constant(_proxy), typeof(DynamicProxy).GetMethod(methodName), list), dynamicMetaObject.Expression, fallbackResult.Expression, binder.ReturnType)), GetRestrictions().Merge(dynamicMetaObject.Restrictions).Merge(fallbackResult.Restrictions)); } private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObjectBinder binder, IEnumerable args, Fallback fallback) { DynamicMetaObject dynamicMetaObject = fallback(null); ParameterExpression parameterExpression = System.Linq.Expressions.Expression.Parameter(typeof(object), null); IList list = new List(); list.Add(System.Linq.Expressions.Expression.Convert(base.Expression, typeof(T))); list.Add(Constant(binder)); list.AddRange(args); list[list.Count - 1] = System.Linq.Expressions.Expression.Assign(parameterExpression, list[list.Count - 1]); return new DynamicMetaObject(System.Linq.Expressions.Expression.Block(new ParameterExpression[1] { parameterExpression }, System.Linq.Expressions.Expression.Condition(System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression.Constant(_proxy), typeof(DynamicProxy).GetMethod(methodName), list), parameterExpression, dynamicMetaObject.Expression, typeof(object))), GetRestrictions().Merge(dynamicMetaObject.Restrictions)); } private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback) { DynamicMetaObject dynamicMetaObject = fallback(null); IList list = new List(); list.Add(System.Linq.Expressions.Expression.Convert(base.Expression, typeof(T))); list.Add(Constant(binder)); list.AddRange(args); return new DynamicMetaObject(System.Linq.Expressions.Expression.Condition(System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression.Constant(_proxy), typeof(DynamicProxy).GetMethod(methodName), list), System.Linq.Expressions.Expression.Empty(), dynamicMetaObject.Expression, typeof(void)), GetRestrictions().Merge(dynamicMetaObject.Restrictions)); } private BindingRestrictions GetRestrictions() { if (base.Value != null || !base.HasValue) { return BindingRestrictions.GetTypeRestriction(base.Expression, base.LimitType); } return BindingRestrictions.GetInstanceRestriction(base.Expression, null); } public override IEnumerable GetDynamicMemberNames() { return _proxy.GetDynamicMemberNames((T)base.Value); } } internal class DynamicReflectionDelegateFactory : ReflectionDelegateFactory { internal static DynamicReflectionDelegateFactory Instance { get; } = new DynamicReflectionDelegateFactory(); private static DynamicMethod CreateDynamicMethod(string name, Type? returnType, Type[] parameterTypes, Type owner) { if (owner.IsInterface()) { return new DynamicMethod(name, returnType, parameterTypes, owner.Module, skipVisibility: true); } return new DynamicMethod(name, returnType, parameterTypes, owner, skipVisibility: true); } public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) { DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new Type[1] { typeof(object[]) }, method.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateMethodCallIL(method, iLGenerator, 0); return (ObjectConstructor)dynamicMethod.CreateDelegate(typeof(ObjectConstructor)); } public override MethodCall CreateMethodCall(MethodBase method) { DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new Type[2] { typeof(object), typeof(object[]) }, method.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateMethodCallIL(method, iLGenerator, 1); return (MethodCall)dynamicMethod.CreateDelegate(typeof(MethodCall)); } private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator, int argsIndex) { ParameterInfo[] parameters = method.GetParameters(); Label label = generator.DefineLabel(); generator.Emit(OpCodes.Ldarg, argsIndex); generator.Emit(OpCodes.Ldlen); generator.Emit(OpCodes.Ldc_I4, parameters.Length); generator.Emit(OpCodes.Beq, label); generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(ReflectionUtils.EmptyTypes)); generator.Emit(OpCodes.Throw); generator.MarkLabel(label); if (!method.IsConstructor && !method.IsStatic) { generator.PushInstance(method.DeclaringType); } LocalBuilder local = generator.DeclareLocal(typeof(IConvertible)); LocalBuilder local2 = generator.DeclareLocal(typeof(object)); OpCode opcode = ((parameters.Length < 256) ? OpCodes.Ldloca_S : OpCodes.Ldloca); OpCode opcode2 = ((parameters.Length < 256) ? OpCodes.Ldloc_S : OpCodes.Ldloc); for (int i = 0; i < parameters.Length; i++) { ParameterInfo parameterInfo = parameters[i]; Type parameterType = parameterInfo.ParameterType; if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); LocalBuilder local3 = generator.DeclareLocal(parameterType); if (!parameterInfo.IsOut) { generator.PushArrayInstance(argsIndex, i); if (parameterType.IsValueType()) { Label label2 = generator.DefineLabel(); Label label3 = generator.DefineLabel(); generator.Emit(OpCodes.Brtrue_S, label2); generator.Emit(opcode, local3); generator.Emit(OpCodes.Initobj, parameterType); generator.Emit(OpCodes.Br_S, label3); generator.MarkLabel(label2); generator.PushArrayInstance(argsIndex, i); generator.UnboxIfNeeded(parameterType); generator.Emit(OpCodes.Stloc_S, local3); generator.MarkLabel(label3); } else { generator.UnboxIfNeeded(parameterType); generator.Emit(OpCodes.Stloc_S, local3); } } generator.Emit(opcode, local3); } else if (parameterType.IsValueType()) { generator.PushArrayInstance(argsIndex, i); generator.Emit(OpCodes.Stloc_S, local2); Label label4 = generator.DefineLabel(); Label label5 = generator.DefineLabel(); generator.Emit(OpCodes.Ldloc_S, local2); generator.Emit(OpCodes.Brtrue_S, label4); LocalBuilder local4 = generator.DeclareLocal(parameterType); generator.Emit(opcode, local4); generator.Emit(OpCodes.Initobj, parameterType); generator.Emit(opcode2, local4); generator.Emit(OpCodes.Br_S, label5); generator.MarkLabel(label4); if (parameterType.IsPrimitive()) { MethodInfo method2 = typeof(IConvertible).GetMethod("To" + parameterType.Name, new Type[1] { typeof(IFormatProvider) }); if (method2 != null) { Label label6 = generator.DefineLabel(); generator.Emit(OpCodes.Ldloc_S, local2); generator.Emit(OpCodes.Isinst, parameterType); generator.Emit(OpCodes.Brtrue_S, label6); generator.Emit(OpCodes.Ldloc_S, local2); generator.Emit(OpCodes.Isinst, typeof(IConvertible)); generator.Emit(OpCodes.Stloc_S, local); generator.Emit(OpCodes.Ldloc_S, local); generator.Emit(OpCodes.Brfalse_S, label6); generator.Emit(OpCodes.Ldloc_S, local); generator.Emit(OpCodes.Ldnull); generator.Emit(OpCodes.Callvirt, method2); generator.Emit(OpCodes.Br_S, label5); generator.MarkLabel(label6); } } generator.Emit(OpCodes.Ldloc_S, local2); generator.UnboxIfNeeded(parameterType); generator.MarkLabel(label5); } else { generator.PushArrayInstance(argsIndex, i); generator.UnboxIfNeeded(parameterType); } } if (method.IsConstructor) { generator.Emit(OpCodes.Newobj, (ConstructorInfo)method); } else { generator.CallMethod((MethodInfo)method); } Type type = (method.IsConstructor ? method.DeclaringType : ((MethodInfo)method).ReturnType); if (type != typeof(void)) { generator.BoxIfNeeded(type); } else { generator.Emit(OpCodes.Ldnull); } generator.Return(); } public override Func CreateDefaultConstructor(Type type) { DynamicMethod dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(T), ReflectionUtils.EmptyTypes, type); dynamicMethod.InitLocals = true; ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateDefaultConstructorIL(type, iLGenerator, typeof(T)); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator, Type delegateType) { if (type.IsValueType()) { generator.DeclareLocal(type); generator.Emit(OpCodes.Ldloc_0); if (type != delegateType) { generator.Emit(OpCodes.Box, type); } } else { ConstructorInfo constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, ReflectionUtils.EmptyTypes, null); if (constructor == null) { throw new ArgumentException("Could not get constructor for {0}.".FormatWith(CultureInfo.InvariantCulture, type)); } generator.Emit(OpCodes.Newobj, constructor); } generator.Return(); } public override Func CreateGet(PropertyInfo propertyInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(object), new Type[1] { typeof(T) }, propertyInfo.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateGetPropertyIL(propertyInfo, iLGenerator); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) { MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod == null) { throw new ArgumentException("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture, propertyInfo.Name)); } if (!getMethod.IsStatic) { generator.PushInstance(propertyInfo.DeclaringType); } generator.CallMethod(getMethod); generator.BoxIfNeeded(propertyInfo.PropertyType); generator.Return(); } public override Func CreateGet(FieldInfo fieldInfo) { if (fieldInfo.IsLiteral) { object constantValue = fieldInfo.GetValue(null); return (T o) => constantValue; } DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new Type[1] { typeof(object) }, fieldInfo.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateGetFieldIL(fieldInfo, iLGenerator); return (Func)dynamicMethod.CreateDelegate(typeof(Func)); } private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator) { if (!fieldInfo.IsStatic) { generator.PushInstance(fieldInfo.DeclaringType); generator.Emit(OpCodes.Ldfld, fieldInfo); } else { generator.Emit(OpCodes.Ldsfld, fieldInfo); } generator.BoxIfNeeded(fieldInfo.FieldType); generator.Return(); } public override Action CreateSet(FieldInfo fieldInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new Type[2] { typeof(T), typeof(object) }, fieldInfo.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateSetFieldIL(fieldInfo, iLGenerator); return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator generator) { if (!fieldInfo.IsStatic) { generator.PushInstance(fieldInfo.DeclaringType); } generator.Emit(OpCodes.Ldarg_1); generator.UnboxIfNeeded(fieldInfo.FieldType); if (!fieldInfo.IsStatic) { generator.Emit(OpCodes.Stfld, fieldInfo); } else { generator.Emit(OpCodes.Stsfld, fieldInfo); } generator.Return(); } public override Action CreateSet(PropertyInfo propertyInfo) { DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new Type[2] { typeof(T), typeof(object) }, propertyInfo.DeclaringType); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); GenerateCreateSetPropertyIL(propertyInfo, iLGenerator); return (Action)dynamicMethod.CreateDelegate(typeof(Action)); } internal static void GenerateCreateSetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator) { MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); if (!setMethod.IsStatic) { generator.PushInstance(propertyInfo.DeclaringType); } generator.Emit(OpCodes.Ldarg_1); generator.UnboxIfNeeded(propertyInfo.PropertyType); generator.CallMethod(setMethod); generator.Return(); } } internal static class DynamicUtils { internal static class BinderWrapper { public const string CSharpAssemblyName = "Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private const string BinderTypeName = "Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private const string CSharpArgumentInfoTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private const string CSharpArgumentInfoFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private const string CSharpBinderFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"; private static object? _getCSharpArgumentInfoArray; private static object? _setCSharpArgumentInfoArray; private static MethodCall? _getMemberCall; private static MethodCall? _setMemberCall; private static bool _init; private static void Init() { if (!_init) { if (Type.GetType("Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false) == null) { throw new InvalidOperationException("Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.".FormatWith(CultureInfo.InvariantCulture, "Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")); } _getCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(default(int)); _setCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0, 3); CreateMemberCalls(); _init = true; } } private static object CreateSharpArgumentInfoArray(params int[] values) { Type type = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Type type2 = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Array array = Array.CreateInstance(type, values.Length); for (int i = 0; i < values.Length; i++) { object value = type.GetMethod("Create", new Type[2] { type2, typeof(string) }).Invoke(null, new object[2] { 0, null }); array.SetValue(value, i); } return array; } private static void CreateMemberCalls() { Type type = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Type type2 = Type.GetType("Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Type type3 = Type.GetType("Microsoft.CSharp.RuntimeBinder.Binder, Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: true); Type type4 = typeof(IEnumerable<>).MakeGenericType(type); MethodInfo method = type3.GetMethod("GetMember", new Type[4] { type2, typeof(string), typeof(Type), type4 }); _getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(method); MethodInfo method2 = type3.GetMethod("SetMember", new Type[4] { type2, typeof(string), typeof(Type), type4 }); _setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(method2); } public static CallSiteBinder GetMember(string name, Type context) { Init(); return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray); } public static CallSiteBinder SetMember(string name, Type context) { Init(); return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray); } } public static IEnumerable GetDynamicMemberNames(this IDynamicMetaObjectProvider dynamicProvider) { return dynamicProvider.GetMetaObject(Expression.Constant(dynamicProvider)).GetDynamicMemberNames(); } } internal class NoThrowGetBinderMember : GetMemberBinder { private readonly GetMemberBinder _innerBinder; public NoThrowGetBinderMember(GetMemberBinder innerBinder) : base(innerBinder.Name, innerBinder.IgnoreCase) { _innerBinder = innerBinder; } public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject? errorSuggestion) { DynamicMetaObject dynamicMetaObject = _innerBinder.Bind(target, CollectionUtils.ArrayEmpty()); return new DynamicMetaObject(new NoThrowExpressionVisitor().Visit(dynamicMetaObject.Expression), dynamicMetaObject.Restrictions); } } internal class NoThrowSetBinderMember : SetMemberBinder { private readonly SetMemberBinder _innerBinder; public NoThrowSetBinderMember(SetMemberBinder innerBinder) : base(innerBinder.Name, innerBinder.IgnoreCase) { _innerBinder = innerBinder; } public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject? errorSuggestion) { DynamicMetaObject dynamicMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[1] { value }); return new DynamicMetaObject(new NoThrowExpressionVisitor().Visit(dynamicMetaObject.Expression), dynamicMetaObject.Restrictions); } } internal class NoThrowExpressionVisitor : ExpressionVisitor { internal static readonly object ErrorResult = new object(); protected override Expression VisitConditional(ConditionalExpression node) { if (node.IfFalse.NodeType == ExpressionType.Throw) { return Expression.Condition(node.Test, node.IfTrue, Expression.Constant(ErrorResult)); } return base.VisitConditional(node); } } internal class EnumInfo { public readonly bool IsFlags; public readonly ulong[] Values; public readonly string[] Names; public readonly string[] ResolvedNames; public EnumInfo(bool isFlags, ulong[] values, string[] names, string[] resolvedNames) { IsFlags = isFlags; Values = values; Names = names; ResolvedNames = resolvedNames; } } internal static class EnumUtils { private const char EnumSeparatorChar = ','; private const string EnumSeparatorString = ", "; private static readonly ThreadSafeStore, EnumInfo> ValuesAndNamesPerEnum = new ThreadSafeStore, EnumInfo>(InitializeValuesAndNames); private static CamelCaseNamingStrategy _camelCaseNamingStrategy = new CamelCaseNamingStrategy(); private static EnumInfo InitializeValuesAndNames(StructMultiKey key) { Type value = key.Value1; string[] names = Enum.GetNames(value); string[] array = new string[names.Length]; ulong[] array2 = new ulong[names.Length]; for (int i = 0; i < names.Length; i++) { string text = names[i]; FieldInfo field = value.GetField(text, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); array2[i] = ToUInt64(field.GetValue(null)); string text2 = (from EnumMemberAttribute a in field.GetCustomAttributes(typeof(EnumMemberAttribute), inherit: true) select a.Value).SingleOrDefault(); bool hasSpecifiedName = text2 != null; if (text2 == null) { text2 = text; } string text3 = text2; if (Array.IndexOf(array, text3, 0, i) != -1) { throw new InvalidOperationException("Enum name '{0}' already exists on enum '{1}'.".FormatWith(CultureInfo.InvariantCulture, text3, value.Name)); } array[i] = ((key.Value2 != null) ? key.Value2.GetPropertyName(text3, hasSpecifiedName) : text3); } return new EnumInfo(value.IsDefined(typeof(FlagsAttribute), inherit: false), array2, names, array); } public static IList GetFlagsValues(T value) where T : struct { Type typeFromHandle = typeof(T); if (!typeFromHandle.IsDefined(typeof(FlagsAttribute), inherit: false)) { throw new ArgumentException("Enum type {0} is not a set of flags.".FormatWith(CultureInfo.InvariantCulture, typeFromHandle)); } Type underlyingType = Enum.GetUnderlyingType(value.GetType()); ulong num = ToUInt64(value); EnumInfo enumValuesAndNames = GetEnumValuesAndNames(typeFromHandle); IList list = new List(); for (int i = 0; i < enumValuesAndNames.Values.Length; i++) { ulong num2 = enumValuesAndNames.Values[i]; if ((num & num2) == num2 && num2 != 0L) { list.Add((T)Convert.ChangeType(num2, underlyingType, CultureInfo.CurrentCulture)); } } if (list.Count == 0 && enumValuesAndNames.Values.Any((ulong v) => v == 0)) { list.Add(default(T)); } return list; } public static bool TryToString(Type enumType, object value, bool camelCase, [NotNullWhen(true)] out string? name) { return TryToString(enumType, value, camelCase ? _camelCaseNamingStrategy : null, out name); } public static bool TryToString(Type enumType, object value, NamingStrategy? namingStrategy, [NotNullWhen(true)] out string? name) { EnumInfo enumInfo = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); ulong num = ToUInt64(value); if (!enumInfo.IsFlags) { int num2 = Array.BinarySearch(enumInfo.Values, num); if (num2 >= 0) { name = enumInfo.ResolvedNames[num2]; return true; } name = null; return false; } name = InternalFlagsFormat(enumInfo, num); return name != null; } private static string? InternalFlagsFormat(EnumInfo entry, ulong result) { string[] resolvedNames = entry.ResolvedNames; ulong[] values = entry.Values; int num = values.Length - 1; StringBuilder stringBuilder = new StringBuilder(); bool flag = true; ulong num2 = result; while (num >= 0 && (num != 0 || values[num] != 0L)) { if ((result & values[num]) == values[num]) { result -= values[num]; if (!flag) { stringBuilder.Insert(0, ", "); } string value = resolvedNames[num]; stringBuilder.Insert(0, value); flag = false; } num--; } if (result != 0L) { return null; } if (num2 == 0L) { if (values.Length != 0 && values[0] == 0L) { return resolvedNames[0]; } return null; } return stringBuilder.ToString(); } public static EnumInfo GetEnumValuesAndNames(Type enumType) { return ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, null)); } private static ulong ToUInt64(object value) { bool isEnum; return ConvertUtils.GetTypeCode(value.GetType(), out isEnum) switch { PrimitiveTypeCode.SByte => (ulong)(sbyte)value, PrimitiveTypeCode.Byte => (byte)value, PrimitiveTypeCode.Boolean => Convert.ToByte((bool)value), PrimitiveTypeCode.Int16 => (ulong)(short)value, PrimitiveTypeCode.UInt16 => (ushort)value, PrimitiveTypeCode.Char => (char)value, PrimitiveTypeCode.UInt32 => (uint)value, PrimitiveTypeCode.Int32 => (ulong)(int)value, PrimitiveTypeCode.UInt64 => (ulong)value, PrimitiveTypeCode.Int64 => (ulong)(long)value, _ => throw new InvalidOperationException("Unknown enum type."), }; } public static object ParseEnum(Type enumType, NamingStrategy? namingStrategy, string value, bool disallowNumber) { ValidationUtils.ArgumentNotNull(enumType, "enumType"); ValidationUtils.ArgumentNotNull(value, "value"); if (!enumType.IsEnum()) { throw new ArgumentException("Type provided must be an Enum.", "enumType"); } EnumInfo enumInfo = ValuesAndNamesPerEnum.Get(new StructMultiKey(enumType, namingStrategy)); string[] names = enumInfo.Names; string[] resolvedNames = enumInfo.ResolvedNames; ulong[] values = enumInfo.Values; int? num = FindIndexByName(resolvedNames, value, 0, value.Length, StringComparison.Ordinal); if (num.HasValue) { return Enum.ToObject(enumType, values[num.Value]); } int num2 = -1; for (int i = 0; i < value.Length; i++) { if (!char.IsWhiteSpace(value[i])) { num2 = i; break; } } if (num2 == -1) { throw new ArgumentException("Must specify valid information for parsing in the string."); } char c = value[num2]; if (char.IsDigit(c) || c == '-' || c == '+') { Type underlyingType = Enum.GetUnderlyingType(enumType); value = value.Trim(); object obj = null; try { obj = Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture); } catch (FormatException) { } if (obj != null) { if (disallowNumber) { throw new FormatException("Integer string '{0}' is not allowed.".FormatWith(CultureInfo.InvariantCulture, value)); } return Enum.ToObject(enumType, obj); } } ulong num3 = 0uL; int j = num2; while (j <= value.Length) { int num4 = value.IndexOf(',', j); if (num4 == -1) { num4 = value.Length; } int num5 = num4; for (; j < num4 && char.IsWhiteSpace(value[j]); j++) { } while (num5 > j && char.IsWhiteSpace(value[num5 - 1])) { num5--; } int valueSubstringLength = num5 - j; num = MatchName(value, names, resolvedNames, j, valueSubstringLength, StringComparison.Ordinal); if (!num.HasValue) { num = MatchName(value, names, resolvedNames, j, valueSubstringLength, StringComparison.OrdinalIgnoreCase); } if (!num.HasValue) { num = FindIndexByName(resolvedNames, value, 0, value.Length, StringComparison.OrdinalIgnoreCase); if (num.HasValue) { return Enum.ToObject(enumType, values[num.Value]); } throw new ArgumentException("Requested value '{0}' was not found.".FormatWith(CultureInfo.InvariantCulture, value)); } num3 |= values[num.Value]; j = num4 + 1; } return Enum.ToObject(enumType, num3); } private static int? MatchName(string value, string[] enumNames, string[] resolvedNames, int valueIndex, int valueSubstringLength, StringComparison comparison) { int? result = FindIndexByName(resolvedNames, value, valueIndex, valueSubstringLength, comparison); if (!result.HasValue) { result = FindIndexByName(enumNames, value, valueIndex, valueSubstringLength, comparison); } return result; } private static int? FindIndexByName(string[] enumNames, string value, int valueIndex, int valueSubstringLength, StringComparison comparison) { for (int i = 0; i < enumNames.Length; i++) { if (enumNames[i].Length == valueSubstringLength && string.Compare(enumNames[i], 0, value, valueIndex, valueSubstringLength, comparison) == 0) { return i; } } return null; } } internal class ExpressionReflectionDelegateFactory : ReflectionDelegateFactory { private class ByRefParameter { public Expression Value; public ParameterExpression Variable; public bool IsOut; public ByRefParameter(Expression value, ParameterExpression variable, bool isOut) { Value = value; Variable = variable; IsOut = isOut; } } private static readonly ExpressionReflectionDelegateFactory _instance = new ExpressionReflectionDelegateFactory(); internal static ReflectionDelegateFactory Instance => _instance; public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) { ValidationUtils.ArgumentNotNull(method, "method"); Type typeFromHandle = typeof(object); ParameterExpression parameterExpression = Expression.Parameter(typeof(object[]), "args"); Expression body = BuildMethodCall(method, typeFromHandle, null, parameterExpression); return (ObjectConstructor)Expression.Lambda(typeof(ObjectConstructor), body, parameterExpression).Compile(); } public override MethodCall CreateMethodCall(MethodBase method) { ValidationUtils.ArgumentNotNull(method, "method"); Type typeFromHandle = typeof(object); ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle, "target"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object[]), "args"); Expression body = BuildMethodCall(method, typeFromHandle, parameterExpression, parameterExpression2); return (MethodCall)Expression.Lambda(typeof(MethodCall), body, parameterExpression, parameterExpression2).Compile(); } private Expression BuildMethodCall(MethodBase method, Type type, ParameterExpression? targetParameterExpression, ParameterExpression argsParameterExpression) { ParameterInfo[] parameters = method.GetParameters(); Expression[] array; IList list; if (parameters.Length == 0) { array = CollectionUtils.ArrayEmpty(); list = CollectionUtils.ArrayEmpty(); } else { array = new Expression[parameters.Length]; list = new List(); for (int i = 0; i < parameters.Length; i++) { ParameterInfo parameterInfo = parameters[i]; Type type2 = parameterInfo.ParameterType; bool flag = false; if (type2.IsByRef) { type2 = type2.GetElementType(); flag = true; } Expression index = Expression.Constant(i); Expression expression = Expression.ArrayIndex(argsParameterExpression, index); Expression expression2 = EnsureCastExpression(expression, type2, !flag); if (flag) { ParameterExpression parameterExpression = Expression.Variable(type2); list.Add(new ByRefParameter(expression2, parameterExpression, parameterInfo.IsOut)); expression2 = parameterExpression; } array[i] = expression2; } } Expression expression3 = (method.IsConstructor ? ((Expression)Expression.New((ConstructorInfo)method, array)) : ((Expression)((!method.IsStatic) ? Expression.Call(EnsureCastExpression(targetParameterExpression, method.DeclaringType), (MethodInfo)method, array) : Expression.Call((MethodInfo)method, array)))); expression3 = ((!(method is MethodInfo methodInfo)) ? EnsureCastExpression(expression3, type) : ((!(methodInfo.ReturnType != typeof(void))) ? Expression.Block(expression3, Expression.Constant(null)) : EnsureCastExpression(expression3, type))); if (list.Count > 0) { IList list2 = new List(); IList list3 = new List(); foreach (ByRefParameter item in list) { if (!item.IsOut) { list3.Add(Expression.Assign(item.Variable, item.Value)); } list2.Add(item.Variable); } list3.Add(expression3); expression3 = Expression.Block(list2, list3); } return expression3; } public override Func CreateDefaultConstructor(Type type) { Type type2 = type; ValidationUtils.ArgumentNotNull(type2, "type"); if (type2.IsAbstract()) { return () => (T)Activator.CreateInstance(type2); } try { Type typeFromHandle = typeof(T); Expression expression = Expression.New(type2); expression = EnsureCastExpression(expression, typeFromHandle); return (Func)Expression.Lambda(typeof(Func), expression).Compile(); } catch { return () => (T)Activator.CreateInstance(type2); } } public override Func CreateGet(PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo"); Type typeFromHandle = typeof(T); Type typeFromHandle2 = typeof(object); ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle, "instance"); MethodInfo? getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod == null) { throw new ArgumentException("Property does not have a getter."); } Expression expression = ((!getMethod.IsStatic) ? Expression.MakeMemberAccess(EnsureCastExpression(parameterExpression, propertyInfo.DeclaringType), propertyInfo) : Expression.MakeMemberAccess(null, propertyInfo)); expression = EnsureCastExpression(expression, typeFromHandle2); return (Func)Expression.Lambda(typeof(Func), expression, parameterExpression).Compile(); } public override Func CreateGet(FieldInfo fieldInfo) { ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo"); ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "source"); Expression expression = ((!fieldInfo.IsStatic) ? Expression.Field(EnsureCastExpression(parameterExpression, fieldInfo.DeclaringType), fieldInfo) : Expression.Field(null, fieldInfo)); expression = EnsureCastExpression(expression, typeof(object)); return Expression.Lambda>(expression, new ParameterExpression[1] { parameterExpression }).Compile(); } public override Action CreateSet(FieldInfo fieldInfo) { ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo"); if (fieldInfo.DeclaringType.IsValueType() || fieldInfo.IsInitOnly) { return LateBoundReflectionDelegateFactory.Instance.CreateSet(fieldInfo); } ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "source"); ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value"); Expression expression = ((!fieldInfo.IsStatic) ? Expression.Field(EnsureCastExpression(parameterExpression, fieldInfo.DeclaringType), fieldInfo) : Expression.Field(null, fieldInfo)); Expression right = EnsureCastExpression(parameterExpression2, expression.Type); BinaryExpression body = Expression.Assign(expression, right); return (Action)Expression.Lambda(typeof(Action), body, parameterExpression, parameterExpression2).Compile(); } public override Action CreateSet(PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo"); if (propertyInfo.DeclaringType.IsValueType()) { return LateBoundReflectionDelegateFactory.Instance.CreateSet(propertyInfo); } Type typeFromHandle = typeof(T); Type typeFromHandle2 = typeof(object); ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle, "instance"); ParameterExpression parameterExpression2 = Expression.Parameter(typeFromHandle2, "value"); Expression expression = EnsureCastExpression(parameterExpression2, propertyInfo.PropertyType); MethodInfo setMethod = propertyInfo.GetSetMethod(nonPublic: true); if (setMethod == null) { throw new ArgumentException("Property does not have a setter."); } return (Action)Expression.Lambda(body: (!setMethod.IsStatic) ? Expression.Call(EnsureCastExpression(parameterExpression, propertyInfo.DeclaringType), setMethod, expression) : Expression.Call(setMethod, expression), delegateType: typeof(Action), parameters: new ParameterExpression[2] { parameterExpression, parameterExpression2 }).Compile(); } private Expression EnsureCastExpression(Expression expression, Type targetType, bool allowWidening = false) { Type type = expression.Type; if (type == targetType || (!type.IsValueType() && targetType.IsAssignableFrom(type))) { return expression; } if (targetType.IsValueType()) { Expression expression2 = Expression.Unbox(expression, targetType); if (allowWidening && targetType.IsPrimitive()) { MethodInfo method = typeof(Convert).GetMethod("To" + targetType.Name, new Type[1] { typeof(object) }); if (method != null) { expression2 = Expression.Condition(Expression.TypeIs(expression, targetType), expression2, Expression.Call(method, expression)); } } return Expression.Condition(Expression.Equal(expression, Expression.Constant(null, typeof(object))), Expression.Default(targetType), expression2); } return Expression.Convert(expression, targetType); } } internal class FSharpFunction { private readonly object? _instance; private readonly MethodCall _invoker; public FSharpFunction(object? instance, MethodCall invoker) { _instance = instance; _invoker = invoker; } public object Invoke(params object[] args) { return _invoker(_instance, args); } } internal class FSharpUtils { private static readonly object Lock = new object(); private static FSharpUtils? _instance; private MethodInfo _ofSeq; private Type _mapType; public const string FSharpSetTypeName = "FSharpSet`1"; public const string FSharpListTypeName = "FSharpList`1"; public const string FSharpMapTypeName = "FSharpMap`2"; public static FSharpUtils Instance => _instance; public Assembly FSharpCoreAssembly { get; private set; } public MethodCall IsUnion { get; private set; } public MethodCall GetUnionCases { get; private set; } public MethodCall PreComputeUnionTagReader { get; private set; } public MethodCall PreComputeUnionReader { get; private set; } public MethodCall PreComputeUnionConstructor { get; private set; } public Func GetUnionCaseInfoDeclaringType { get; private set; } public Func GetUnionCaseInfoName { get; private set; } public Func GetUnionCaseInfoTag { get; private set; } public MethodCall GetUnionCaseInfoFields { get; private set; } private FSharpUtils(Assembly fsharpCoreAssembly) { FSharpCoreAssembly = fsharpCoreAssembly; Type? type = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType"); MethodInfo methodWithNonPublicFallback = GetMethodWithNonPublicFallback(type, "IsUnion", BindingFlags.Static | BindingFlags.Public); IsUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodWithNonPublicFallback); MethodInfo methodWithNonPublicFallback2 = GetMethodWithNonPublicFallback(type, "GetUnionCases", BindingFlags.Static | BindingFlags.Public); GetUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodWithNonPublicFallback2); Type type2 = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue"); PreComputeUnionTagReader = CreateFSharpFuncCall(type2, "PreComputeUnionTagReader"); PreComputeUnionReader = CreateFSharpFuncCall(type2, "PreComputeUnionReader"); PreComputeUnionConstructor = CreateFSharpFuncCall(type2, "PreComputeUnionConstructor"); Type type3 = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo"); GetUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(type3.GetProperty("Name")); GetUnionCaseInfoTag = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(type3.GetProperty("Tag")); GetUnionCaseInfoDeclaringType = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(type3.GetProperty("DeclaringType")); GetUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(type3.GetMethod("GetFields")); Type type4 = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule"); _ofSeq = type4.GetMethod("OfSeq"); _mapType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpMap`2"); } public static void EnsureInitialized(Assembly fsharpCoreAssembly) { if (_instance != null) { return; } lock (Lock) { if (_instance == null) { _instance = new FSharpUtils(fsharpCoreAssembly); } } } private static MethodInfo GetMethodWithNonPublicFallback(Type type, string methodName, BindingFlags bindingFlags) { MethodInfo method = type.GetMethod(methodName, bindingFlags); if (method == null && (bindingFlags & BindingFlags.NonPublic) != BindingFlags.NonPublic) { method = type.GetMethod(methodName, bindingFlags | BindingFlags.NonPublic); } return method; } private static MethodCall CreateFSharpFuncCall(Type type, string methodName) { MethodInfo methodWithNonPublicFallback = GetMethodWithNonPublicFallback(type, methodName, BindingFlags.Static | BindingFlags.Public); MethodInfo method = methodWithNonPublicFallback.ReturnType.GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public); MethodCall call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodWithNonPublicFallback); MethodCall invoke = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(method); return (object? target, object?[] args) => new FSharpFunction(call(target, args), invoke); } public ObjectConstructor CreateSeq(Type t) { MethodInfo method = _ofSeq.MakeGenericMethod(t); return JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); } public ObjectConstructor CreateMap(Type keyType, Type valueType) { return (ObjectConstructor)typeof(FSharpUtils).GetMethod("BuildMapCreator").MakeGenericMethod(keyType, valueType).Invoke(this, null); } public ObjectConstructor BuildMapCreator() { ConstructorInfo constructor = _mapType.MakeGenericType(typeof(TKey), typeof(TValue)).GetConstructor(new Type[1] { typeof(IEnumerable>) }); ObjectConstructor ctorDelegate = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); return delegate(object?[] args) { IEnumerable> enumerable = ((IEnumerable>)args[0]).Select((KeyValuePair kv) => new Tuple(kv.Key, kv.Value)); return ctorDelegate(enumerable); }; } } internal static class ILGeneratorExtensions { public static void PushInstance(this ILGenerator generator, Type type) { generator.Emit(OpCodes.Ldarg_0); if (type.IsValueType()) { generator.Emit(OpCodes.Unbox, type); } else { generator.Emit(OpCodes.Castclass, type); } } public static void PushArrayInstance(this ILGenerator generator, int argsIndex, int arrayIndex) { generator.Emit(OpCodes.Ldarg, argsIndex); generator.Emit(OpCodes.Ldc_I4, arrayIndex); generator.Emit(OpCodes.Ldelem_Ref); } public static void BoxIfNeeded(this ILGenerator generator, Type type) { if (type.IsValueType()) { generator.Emit(OpCodes.Box, type); } else { generator.Emit(OpCodes.Castclass, type); } } public static void UnboxIfNeeded(this ILGenerator generator, Type type) { if (type.IsValueType()) { generator.Emit(OpCodes.Unbox_Any, type); } else { generator.Emit(OpCodes.Castclass, type); } } public static void CallMethod(this ILGenerator generator, MethodInfo methodInfo) { if (methodInfo.IsFinal || !methodInfo.IsVirtual) { generator.Emit(OpCodes.Call, methodInfo); } else { generator.Emit(OpCodes.Callvirt, methodInfo); } } public static void Return(this ILGenerator generator) { generator.Emit(OpCodes.Ret); } } internal static class ImmutableCollectionsUtils { internal class ImmutableCollectionTypeInfo { public string ContractTypeName { get; set; } public string CreatedTypeName { get; set; } public string BuilderTypeName { get; set; } public ImmutableCollectionTypeInfo(string contractTypeName, string createdTypeName, string builderTypeName) { ContractTypeName = contractTypeName; CreatedTypeName = createdTypeName; BuilderTypeName = builderTypeName; } } private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1"; private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1"; private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1"; private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1"; private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray"; private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1"; private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList"; private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1"; private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue"; private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1"; private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack"; private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1"; private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet"; private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1"; private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet"; private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1"; private static readonly IList ArrayContractImmutableCollectionDefinitions = new List { new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableList`1", "System.Collections.Immutable.ImmutableList`1", "System.Collections.Immutable.ImmutableList"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableList`1", "System.Collections.Immutable.ImmutableList`1", "System.Collections.Immutable.ImmutableList"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableQueue`1", "System.Collections.Immutable.ImmutableQueue`1", "System.Collections.Immutable.ImmutableQueue"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableQueue`1", "System.Collections.Immutable.ImmutableQueue`1", "System.Collections.Immutable.ImmutableQueue"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableStack`1", "System.Collections.Immutable.ImmutableStack`1", "System.Collections.Immutable.ImmutableStack"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableStack`1", "System.Collections.Immutable.ImmutableStack`1", "System.Collections.Immutable.ImmutableStack"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableSet`1", "System.Collections.Immutable.ImmutableHashSet`1", "System.Collections.Immutable.ImmutableHashSet"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableSortedSet`1", "System.Collections.Immutable.ImmutableSortedSet`1", "System.Collections.Immutable.ImmutableSortedSet"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableHashSet`1", "System.Collections.Immutable.ImmutableHashSet`1", "System.Collections.Immutable.ImmutableHashSet"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableArray`1", "System.Collections.Immutable.ImmutableArray`1", "System.Collections.Immutable.ImmutableArray") }; private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDictionary`2"; private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary"; private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2"; private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary"; private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2"; private static readonly IList DictionaryContractImmutableCollectionDefinitions = new List { new ImmutableCollectionTypeInfo("System.Collections.Immutable.IImmutableDictionary`2", "System.Collections.Immutable.ImmutableDictionary`2", "System.Collections.Immutable.ImmutableDictionary"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableSortedDictionary`2", "System.Collections.Immutable.ImmutableSortedDictionary`2", "System.Collections.Immutable.ImmutableSortedDictionary"), new ImmutableCollectionTypeInfo("System.Collections.Immutable.ImmutableDictionary`2", "System.Collections.Immutable.ImmutableDictionary`2", "System.Collections.Immutable.ImmutableDictionary") }; internal static bool TryBuildImmutableForArrayContract(Type underlyingType, Type collectionItemType, [NotNullWhen(true)] out Type? createdType, [NotNullWhen(true)] out ObjectConstructor? parameterizedCreator) { if (underlyingType.IsGenericType()) { Type genericTypeDefinition = underlyingType.GetGenericTypeDefinition(); string name = genericTypeDefinition.FullName; ImmutableCollectionTypeInfo immutableCollectionTypeInfo = ArrayContractImmutableCollectionDefinitions.FirstOrDefault((ImmutableCollectionTypeInfo d) => d.ContractTypeName == name); if (immutableCollectionTypeInfo != null) { Type type = genericTypeDefinition.Assembly().GetType(immutableCollectionTypeInfo.CreatedTypeName); Type type2 = genericTypeDefinition.Assembly().GetType(immutableCollectionTypeInfo.BuilderTypeName); if (type != null && type2 != null) { MethodInfo methodInfo = type2.GetMethods().FirstOrDefault((MethodInfo m) => m.Name == "CreateRange" && m.GetParameters().Length == 1); if (methodInfo != null) { createdType = type.MakeGenericType(collectionItemType); MethodInfo method = methodInfo.MakeGenericMethod(collectionItemType); parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); return true; } } } } createdType = null; parameterizedCreator = null; return false; } internal static bool TryBuildImmutableForDictionaryContract(Type underlyingType, Type keyItemType, Type valueItemType, [NotNullWhen(true)] out Type? createdType, [NotNullWhen(true)] out ObjectConstructor? parameterizedCreator) { if (underlyingType.IsGenericType()) { Type genericTypeDefinition = underlyingType.GetGenericTypeDefinition(); string name = genericTypeDefinition.FullName; ImmutableCollectionTypeInfo immutableCollectionTypeInfo = DictionaryContractImmutableCollectionDefinitions.FirstOrDefault((ImmutableCollectionTypeInfo d) => d.ContractTypeName == name); if (immutableCollectionTypeInfo != null) { Type type = genericTypeDefinition.Assembly().GetType(immutableCollectionTypeInfo.CreatedTypeName); Type type2 = genericTypeDefinition.Assembly().GetType(immutableCollectionTypeInfo.BuilderTypeName); if (type != null && type2 != null) { MethodInfo methodInfo = type2.GetMethods().FirstOrDefault(delegate(MethodInfo m) { ParameterInfo[] parameters = m.GetParameters(); return m.Name == "CreateRange" && parameters.Length == 1 && parameters[0].ParameterType.IsGenericType() && parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>); }); if (methodInfo != null) { createdType = type.MakeGenericType(keyItemType, valueItemType); MethodInfo method = methodInfo.MakeGenericMethod(keyItemType, valueItemType); parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); return true; } } } } createdType = null; parameterizedCreator = null; return false; } } internal static class BufferUtils { public static char[] RentBuffer(IArrayPool? bufferPool, int minSize) { if (bufferPool == null) { return new char[minSize]; } return bufferPool.Rent(minSize); } public static void ReturnBuffer(IArrayPool? bufferPool, char[]? buffer) { bufferPool?.Return(buffer); } public static char[] EnsureBufferSize(IArrayPool? bufferPool, int size, char[]? buffer) { if (bufferPool == null) { return new char[size]; } if (buffer != null) { bufferPool.Return(buffer); } return bufferPool.Rent(size); } } internal static class JavaScriptUtils { internal static readonly bool[] SingleQuoteCharEscapeFlags; internal static readonly bool[] DoubleQuoteCharEscapeFlags; internal static readonly bool[] HtmlCharEscapeFlags; private const int UnicodeTextLength = 6; private const string EscapedUnicodeText = "!"; static JavaScriptUtils() { SingleQuoteCharEscapeFlags = new bool[128]; DoubleQuoteCharEscapeFlags = new bool[128]; HtmlCharEscapeFlags = new bool[128]; IList list = new List { '\n', '\r', '\t', '\\', '\f', '\b' }; for (int i = 0; i < 32; i++) { list.Add((char)i); } foreach (char item in list.Union(new char[1] { '\'' })) { SingleQuoteCharEscapeFlags[(uint)item] = true; } foreach (char item2 in list.Union(new char[1] { '"' })) { DoubleQuoteCharEscapeFlags[(uint)item2] = true; } foreach (char item3 in list.Union(new char[5] { '"', '\'', '<', '>', '&' })) { HtmlCharEscapeFlags[(uint)item3] = true; } } public static bool[] GetCharEscapeFlags(StringEscapeHandling stringEscapeHandling, char quoteChar) { if (stringEscapeHandling == StringEscapeHandling.EscapeHtml) { return HtmlCharEscapeFlags; } if (quoteChar == '"') { return DoubleQuoteCharEscapeFlags; } return SingleQuoteCharEscapeFlags; } public static bool ShouldEscapeJavaScriptString(string? s, bool[] charEscapeFlags) { if (s == null) { return false; } foreach (char c in s) { if (c >= charEscapeFlags.Length || charEscapeFlags[(uint)c]) { return true; } } return false; } public static void WriteEscapedJavaScriptString(TextWriter writer, string? s, char delimiter, bool appendDelimiters, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, IArrayPool? bufferPool, ref char[]? writeBuffer) { if (appendDelimiters) { writer.Write(delimiter); } if (!StringUtils.IsNullOrEmpty(s)) { int num = FirstCharToEscape(s, charEscapeFlags, stringEscapeHandling); if (num == -1) { writer.Write(s); } else { if (num != 0) { if (writeBuffer == null || writeBuffer.Length < num) { writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, num, writeBuffer); } s.CopyTo(0, writeBuffer, 0, num); writer.Write(writeBuffer, 0, num); } int num2; for (int i = num; i < s.Length; i++) { char c = s[i]; if (c < charEscapeFlags.Length && !charEscapeFlags[(uint)c]) { continue; } string text; switch (c) { case '\t': text = "\\t"; break; case '\n': text = "\\n"; break; case '\r': text = "\\r"; break; case '\f': text = "\\f"; break; case '\b': text = "\\b"; break; case '\\': text = "\\\\"; break; case '\u0085': text = "\\u0085"; break; case '\u2028': text = "\\u2028"; break; case '\u2029': text = "\\u2029"; break; default: if (c < charEscapeFlags.Length || stringEscapeHandling == StringEscapeHandling.EscapeNonAscii) { if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) { text = "\\'"; break; } if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) { text = "\\\""; break; } if (writeBuffer == null || writeBuffer.Length < 6) { writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, 6, writeBuffer); } StringUtils.ToCharAsUnicode(c, writeBuffer); text = "!"; } else { text = null; } break; } if (text == null) { continue; } bool flag = string.Equals(text, "!", StringComparison.Ordinal); if (i > num) { num2 = i - num + (flag ? 6 : 0); int num3 = (flag ? 6 : 0); if (writeBuffer == null || writeBuffer.Length < num2) { char[] array = BufferUtils.RentBuffer(bufferPool, num2); if (flag) { Array.Copy(writeBuffer, array, 6); } BufferUtils.ReturnBuffer(bufferPool, writeBuffer); writeBuffer = array; } s.CopyTo(num, writeBuffer, num3, num2 - num3); writer.Write(writeBuffer, num3, num2 - num3); } num = i + 1; if (!flag) { writer.Write(text); } else { writer.Write(writeBuffer, 0, 6); } } num2 = s.Length - num; if (num2 > 0) { if (writeBuffer == null || writeBuffer.Length < num2) { writeBuffer = BufferUtils.EnsureBufferSize(bufferPool, num2, writeBuffer); } s.CopyTo(num, writeBuffer, 0, num2); writer.Write(writeBuffer, 0, num2); } } } if (appendDelimiters) { writer.Write(delimiter); } } public static string ToEscapedJavaScriptString(string? value, char delimiter, bool appendDelimiters, StringEscapeHandling stringEscapeHandling) { bool[] charEscapeFlags = GetCharEscapeFlags(stringEscapeHandling, delimiter); using StringWriter stringWriter = StringUtils.CreateStringWriter(value?.Length ?? 16); char[] writeBuffer = null; WriteEscapedJavaScriptString(stringWriter, value, delimiter, appendDelimiters, charEscapeFlags, stringEscapeHandling, null, ref writeBuffer); return stringWriter.ToString(); } private static int FirstCharToEscape(string s, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling) { for (int i = 0; i != s.Length; i++) { char c = s[i]; if (c < charEscapeFlags.Length) { if (charEscapeFlags[(uint)c]) { return i; } continue; } if (stringEscapeHandling == StringEscapeHandling.EscapeNonAscii) { return i; } if (c == '\u0085' || c == '\u2028' || c == '\u2029') { return i; } } return -1; } public static Task WriteEscapedJavaScriptStringAsync(TextWriter writer, string s, char delimiter, bool appendDelimiters, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return cancellationToken.FromCanceled(); } if (appendDelimiters) { return WriteEscapedJavaScriptStringWithDelimitersAsync(writer, s, delimiter, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } if (StringUtils.IsNullOrEmpty(s)) { return cancellationToken.CancelIfRequestedAsync() ?? AsyncUtils.CompletedTask; } return WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } private static Task WriteEscapedJavaScriptStringWithDelimitersAsync(TextWriter writer, string s, char delimiter, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { Task task = writer.WriteAsync(delimiter, cancellationToken); if (!task.IsCompletedSuccessfully()) { return WriteEscapedJavaScriptStringWithDelimitersAsync(task, writer, s, delimiter, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } if (!StringUtils.IsNullOrEmpty(s)) { task = WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); if (task.IsCompletedSuccessfully()) { return writer.WriteAsync(delimiter, cancellationToken); } } return WriteCharAsync(task, writer, delimiter, cancellationToken); } private static async Task WriteEscapedJavaScriptStringWithDelimitersAsync(Task task, TextWriter writer, string s, char delimiter, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); if (!StringUtils.IsNullOrEmpty(s)) { await WriteEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } await writer.WriteAsync(delimiter).ConfigureAwait(continueOnCapturedContext: false); } public static async Task WriteCharAsync(Task task, TextWriter writer, char c, CancellationToken cancellationToken) { await task.ConfigureAwait(continueOnCapturedContext: false); await writer.WriteAsync(c, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } private static Task WriteEscapedJavaScriptStringWithoutDelimitersAsync(TextWriter writer, string s, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { int num = FirstCharToEscape(s, charEscapeFlags, stringEscapeHandling); if (num != -1) { return WriteDefinitelyEscapedJavaScriptStringWithoutDelimitersAsync(writer, s, num, charEscapeFlags, stringEscapeHandling, client, writeBuffer, cancellationToken); } return writer.WriteAsync(s, cancellationToken); } private static async Task WriteDefinitelyEscapedJavaScriptStringWithoutDelimitersAsync(TextWriter writer, string s, int lastWritePosition, bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, JsonTextWriter client, char[] writeBuffer, CancellationToken cancellationToken) { if (writeBuffer == null || writeBuffer.Length < lastWritePosition) { writeBuffer = client.EnsureWriteBuffer(lastWritePosition, 6); } if (lastWritePosition != 0) { s.CopyTo(0, writeBuffer, 0, lastWritePosition); await writer.WriteAsync(writeBuffer, 0, lastWritePosition, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } bool isEscapedUnicodeText = false; string escapedValue = null; int num; for (int i = lastWritePosition; i < s.Length; i++) { char c = s[i]; if (c < charEscapeFlags.Length && !charEscapeFlags[(uint)c]) { continue; } switch (c) { case '\t': escapedValue = "\\t"; break; case '\n': escapedValue = "\\n"; break; case '\r': escapedValue = "\\r"; break; case '\f': escapedValue = "\\f"; break; case '\b': escapedValue = "\\b"; break; case '\\': escapedValue = "\\\\"; break; case '\u0085': escapedValue = "\\u0085"; break; case '\u2028': escapedValue = "\\u2028"; break; case '\u2029': escapedValue = "\\u2029"; break; default: if (c >= charEscapeFlags.Length && stringEscapeHandling != StringEscapeHandling.EscapeNonAscii) { continue; } if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) { escapedValue = "\\'"; break; } if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml) { escapedValue = "\\\""; break; } if (writeBuffer.Length < 6) { writeBuffer = client.EnsureWriteBuffer(6, 0); } StringUtils.ToCharAsUnicode(c, writeBuffer); isEscapedUnicodeText = true; break; } if (i > lastWritePosition) { num = i - lastWritePosition + (isEscapedUnicodeText ? 6 : 0); int num2 = (isEscapedUnicodeText ? 6 : 0); if (writeBuffer.Length < num) { writeBuffer = client.EnsureWriteBuffer(num, 6); } s.CopyTo(lastWritePosition, writeBuffer, num2, num - num2); await writer.WriteAsync(writeBuffer, num2, num - num2, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } lastWritePosition = i + 1; if (!isEscapedUnicodeText) { await writer.WriteAsync(escapedValue, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); continue; } await writer.WriteAsync(writeBuffer, 0, 6, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); isEscapedUnicodeText = false; } num = s.Length - lastWritePosition; if (num != 0) { if (writeBuffer.Length < num) { writeBuffer = client.EnsureWriteBuffer(num, 0); } s.CopyTo(lastWritePosition, writeBuffer, 0, num); await writer.WriteAsync(writeBuffer, 0, num, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } public static bool TryGetDateFromConstructorJson(JsonReader reader, out DateTime dateTime, [NotNullWhen(false)] out string? errorMessage) { dateTime = default(DateTime); errorMessage = null; if (!TryGetDateConstructorValue(reader, out var integer, out errorMessage) || !integer.HasValue) { errorMessage = errorMessage ?? "Date constructor has no arguments."; return false; } if (!TryGetDateConstructorValue(reader, out var integer2, out errorMessage)) { return false; } if (integer2.HasValue) { List list = new List { integer.Value, integer2.Value }; while (true) { if (!TryGetDateConstructorValue(reader, out var integer3, out errorMessage)) { return false; } if (!integer3.HasValue) { break; } list.Add(integer3.Value); } if (list.Count > 7) { errorMessage = "Unexpected number of arguments when reading date constructor."; return false; } while (list.Count < 7) { list.Add(0L); } dateTime = new DateTime((int)list[0], (int)list[1] + 1, (int)((list[2] == 0L) ? 1 : list[2]), (int)list[3], (int)list[4], (int)list[5], (int)list[6]); } else { dateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(integer.Value); } return true; } private static bool TryGetDateConstructorValue(JsonReader reader, out long? integer, [NotNullWhen(false)] out string? errorMessage) { integer = null; errorMessage = null; if (!reader.Read()) { errorMessage = "Unexpected end when reading date constructor."; return false; } if (reader.TokenType == JsonToken.EndConstructor) { return true; } if (reader.TokenType != JsonToken.Integer) { errorMessage = "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType; return false; } integer = (long)reader.Value; return true; } } internal static class JsonTokenUtils { internal static bool IsEndToken(JsonToken token) { if ((uint)(token - 13) <= 2u) { return true; } return false; } internal static bool IsStartToken(JsonToken token) { if ((uint)(token - 1) <= 2u) { return true; } return false; } internal static bool IsPrimitiveToken(JsonToken token) { if ((uint)(token - 7) <= 5u || (uint)(token - 16) <= 1u) { return true; } return false; } } internal class LateBoundReflectionDelegateFactory : ReflectionDelegateFactory { private static readonly LateBoundReflectionDelegateFactory _instance = new LateBoundReflectionDelegateFactory(); internal static ReflectionDelegateFactory Instance => _instance; public override ObjectConstructor CreateParameterizedConstructor(MethodBase method) { MethodBase method2 = method; ValidationUtils.ArgumentNotNull(method2, "method"); ConstructorInfo c = method2 as ConstructorInfo; if ((object)c != null) { return (object?[] a) => c.Invoke(a); } return (object?[] a) => method2.Invoke(null, a); } public override MethodCall CreateMethodCall(MethodBase method) { MethodBase method2 = method; ValidationUtils.ArgumentNotNull(method2, "method"); ConstructorInfo c = method2 as ConstructorInfo; if ((object)c != null) { return (T o, object?[] a) => c.Invoke(a); } return (T o, object?[] a) => method2.Invoke(o, a); } public override Func CreateDefaultConstructor(Type type) { Type type2 = type; ValidationUtils.ArgumentNotNull(type2, "type"); if (type2.IsValueType()) { return () => (T)Activator.CreateInstance(type2); } ConstructorInfo constructorInfo = ReflectionUtils.GetDefaultConstructor(type2, nonPublic: true); if (constructorInfo == null) { throw new InvalidOperationException("Unable to find default constructor for " + type2.FullName); } return () => (T)constructorInfo.Invoke(null); } public override Func CreateGet(PropertyInfo propertyInfo) { PropertyInfo propertyInfo2 = propertyInfo; ValidationUtils.ArgumentNotNull(propertyInfo2, "propertyInfo"); return (T o) => propertyInfo2.GetValue(o, null); } public override Func CreateGet(FieldInfo fieldInfo) { FieldInfo fieldInfo2 = fieldInfo; ValidationUtils.ArgumentNotNull(fieldInfo2, "fieldInfo"); return (T o) => fieldInfo2.GetValue(o); } public override Action CreateSet(FieldInfo fieldInfo) { FieldInfo fieldInfo2 = fieldInfo; ValidationUtils.ArgumentNotNull(fieldInfo2, "fieldInfo"); return delegate(T o, object? v) { fieldInfo2.SetValue(o, v); }; } public override Action CreateSet(PropertyInfo propertyInfo) { PropertyInfo propertyInfo2 = propertyInfo; ValidationUtils.ArgumentNotNull(propertyInfo2, "propertyInfo"); return delegate(T o, object? v) { propertyInfo2.SetValue(o, v, null); }; } } internal static class MathUtils { public static int IntLength(ulong i) { if (i < 10000000000L) { if (i < 10) { return 1; } if (i < 100) { return 2; } if (i < 1000) { return 3; } if (i < 10000) { return 4; } if (i < 100000) { return 5; } if (i < 1000000) { return 6; } if (i < 10000000) { return 7; } if (i < 100000000) { return 8; } if (i < 1000000000) { return 9; } return 10; } if (i < 100000000000L) { return 11; } if (i < 1000000000000L) { return 12; } if (i < 10000000000000L) { return 13; } if (i < 100000000000000L) { return 14; } if (i < 1000000000000000L) { return 15; } if (i < 10000000000000000L) { return 16; } if (i < 100000000000000000L) { return 17; } if (i < 1000000000000000000L) { return 18; } if (i < 10000000000000000000uL) { return 19; } return 20; } public static char IntToHex(int n) { if (n <= 9) { return (char)(n + 48); } return (char)(n - 10 + 97); } public static int? Min(int? val1, int? val2) { if (!val1.HasValue) { return val2; } if (!val2.HasValue) { return val1; } return Math.Min(val1.GetValueOrDefault(), val2.GetValueOrDefault()); } public static int? Max(int? val1, int? val2) { if (!val1.HasValue) { return val2; } if (!val2.HasValue) { return val1; } return Math.Max(val1.GetValueOrDefault(), val2.GetValueOrDefault()); } public static double? Max(double? val1, double? val2) { if (!val1.HasValue) { return val2; } if (!val2.HasValue) { return val1; } return Math.Max(val1.GetValueOrDefault(), val2.GetValueOrDefault()); } public static bool ApproxEquals(double d1, double d2) { if (d1 == d2) { return true; } double num = (Math.Abs(d1) + Math.Abs(d2) + 10.0) * 2.220446049250313E-16; double num2 = d1 - d2; if (0.0 - num < num2) { return num > num2; } return false; } } internal delegate TResult MethodCall(T target, params object?[] args); internal delegate T Creator(); internal static class MiscellaneousUtils { [Conditional("DEBUG")] public static void Assert([DoesNotReturnIf(false)] bool condition, string? message = null) { } public static bool ValueEquals(object? objA, object? objB) { if (objA == objB) { return true; } if (objA == null || objB == null) { return false; } if (objA.GetType() != objB.GetType()) { if (ConvertUtils.IsInteger(objA) && ConvertUtils.IsInteger(objB)) { return Convert.ToDecimal(objA, CultureInfo.CurrentCulture).Equals(Convert.ToDecimal(objB, CultureInfo.CurrentCulture)); } if ((objA is double || objA is float || objA is decimal) && (objB is double || objB is float || objB is decimal)) { return MathUtils.ApproxEquals(Convert.ToDouble(objA, CultureInfo.CurrentCulture), Convert.ToDouble(objB, CultureInfo.CurrentCulture)); } return false; } return objA.Equals(objB); } public static ArgumentOutOfRangeException CreateArgumentOutOfRangeException(string paramName, object actualValue, string message) { string message2 = message + Environment.NewLine + "Actual value was {0}.".FormatWith(CultureInfo.InvariantCulture, actualValue); return new ArgumentOutOfRangeException(paramName, message2); } public static string ToString(object? value) { if (value == null) { return "{null}"; } if (!(value is string text)) { return value.ToString(); } return "\"" + text + "\""; } public static int ByteArrayCompare(byte[] a1, byte[] a2) { int num = a1.Length.CompareTo(a2.Length); if (num != 0) { return num; } for (int i = 0; i < a1.Length; i++) { int num2 = a1[i].CompareTo(a2[i]); if (num2 != 0) { return num2; } } return 0; } public static string? GetPrefix(string qualifiedName) { GetQualifiedNameParts(qualifiedName, out string prefix, out string _); return prefix; } public static string GetLocalName(string qualifiedName) { GetQualifiedNameParts(qualifiedName, out string _, out string localName); return localName; } public static void GetQualifiedNameParts(string qualifiedName, out string? prefix, out string localName) { int num = StringUtils.IndexOf(qualifiedName, ':'); if (num == -1 || num == 0 || qualifiedName.Length - 1 == num) { prefix = null; localName = qualifiedName; } else { prefix = qualifiedName.Substring(0, num); localName = qualifiedName.Substring(num + 1); } } internal static RegexOptions GetRegexOptions(string optionsText) { RegexOptions regexOptions = RegexOptions.None; for (int i = 0; i < optionsText.Length; i++) { switch (optionsText[i]) { case 'i': regexOptions |= RegexOptions.IgnoreCase; break; case 'm': regexOptions |= RegexOptions.Multiline; break; case 's': regexOptions |= RegexOptions.Singleline; break; case 'x': regexOptions |= RegexOptions.ExplicitCapture; break; } } return regexOptions; } } internal abstract class ReflectionDelegateFactory { public Func CreateGet(MemberInfo memberInfo) { if (memberInfo is PropertyInfo propertyInfo) { if (propertyInfo.PropertyType.IsByRef) { throw new InvalidOperationException("Could not create getter for {0}. ByRef return values are not supported.".FormatWith(CultureInfo.InvariantCulture, propertyInfo)); } return CreateGet(propertyInfo); } if (memberInfo is FieldInfo fieldInfo) { return CreateGet(fieldInfo); } throw new Exception("Could not create getter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo)); } public Action CreateSet(MemberInfo memberInfo) { if (memberInfo is PropertyInfo propertyInfo) { return CreateSet(propertyInfo); } if (memberInfo is FieldInfo fieldInfo) { return CreateSet(fieldInfo); } throw new Exception("Could not create setter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo)); } public abstract MethodCall CreateMethodCall(MethodBase method); public abstract ObjectConstructor CreateParameterizedConstructor(MethodBase method); public abstract Func CreateDefaultConstructor(Type type); public abstract Func CreateGet(PropertyInfo propertyInfo); public abstract Func CreateGet(FieldInfo fieldInfo); public abstract Action CreateSet(FieldInfo fieldInfo); public abstract Action CreateSet(PropertyInfo propertyInfo); } internal class ReflectionMember { public Type? MemberType { get; set; } public Func? Getter { get; set; } public Action? Setter { get; set; } } internal class ReflectionObject { public ObjectConstructor? Creator { get; } public IDictionary Members { get; } private ReflectionObject(ObjectConstructor? creator) { Members = new Dictionary(); Creator = creator; } public object? GetValue(object target, string member) { return Members[member].Getter(target); } public void SetValue(object target, string member, object? value) { Members[member].Setter(target, value); } public Type GetType(string member) { return Members[member].MemberType; } public static ReflectionObject Create(Type t, params string[] memberNames) { return Create(t, null, memberNames); } public static ReflectionObject Create(Type t, MethodBase? creator, params string[] memberNames) { ReflectionDelegateFactory reflectionDelegateFactory = JsonTypeReflector.ReflectionDelegateFactory; ObjectConstructor creator2 = null; if (creator != null) { creator2 = reflectionDelegateFactory.CreateParameterizedConstructor(creator); } else if (ReflectionUtils.HasDefaultConstructor(t, nonPublic: false)) { Func ctor = reflectionDelegateFactory.CreateDefaultConstructor(t); creator2 = (object?[] args) => ctor(); } ReflectionObject reflectionObject = new ReflectionObject(creator2); foreach (string text in memberNames) { MemberInfo[] member = t.GetMember(text, BindingFlags.Instance | BindingFlags.Public); if (member.Length != 1) { throw new ArgumentException("Expected a single member with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, text)); } MemberInfo memberInfo = member.Single(); ReflectionMember reflectionMember = new ReflectionMember(); switch (memberInfo.MemberType()) { case MemberTypes.Field: case MemberTypes.Property: if (ReflectionUtils.CanReadMemberValue(memberInfo, nonPublic: false)) { reflectionMember.Getter = reflectionDelegateFactory.CreateGet(memberInfo); } if (ReflectionUtils.CanSetMemberValue(memberInfo, nonPublic: false, canSetReadOnly: false)) { reflectionMember.Setter = reflectionDelegateFactory.CreateSet(memberInfo); } break; case MemberTypes.Method: { MethodInfo methodInfo = (MethodInfo)memberInfo; if (!methodInfo.IsPublic) { break; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 0 && methodInfo.ReturnType != typeof(void)) { MethodCall call2 = reflectionDelegateFactory.CreateMethodCall(methodInfo); reflectionMember.Getter = (object target) => call2(target); } else if (parameters.Length == 1 && methodInfo.ReturnType == typeof(void)) { MethodCall call = reflectionDelegateFactory.CreateMethodCall(methodInfo); reflectionMember.Setter = delegate(object target, object? arg) { call(target, arg); }; } break; } default: throw new ArgumentException("Unexpected member type '{0}' for member '{1}'.".FormatWith(CultureInfo.InvariantCulture, memberInfo.MemberType(), memberInfo.Name)); } reflectionMember.MemberType = ReflectionUtils.GetMemberUnderlyingType(memberInfo); reflectionObject.Members[text] = reflectionMember; } return reflectionObject; } } internal static class ReflectionUtils { public static readonly Type[] EmptyTypes; static ReflectionUtils() { EmptyTypes = Type.EmptyTypes; } public static bool IsVirtual(this PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo"); MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod != null && getMethod.IsVirtual) { return true; } getMethod = propertyInfo.GetSetMethod(nonPublic: true); if (getMethod != null && getMethod.IsVirtual) { return true; } return false; } public static MethodInfo? GetBaseDefinition(this PropertyInfo propertyInfo) { ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo"); MethodInfo getMethod = propertyInfo.GetGetMethod(nonPublic: true); if (getMethod != null) { return getMethod.GetBaseDefinition(); } return propertyInfo.GetSetMethod(nonPublic: true)?.GetBaseDefinition(); } public static bool IsPublic(PropertyInfo property) { MethodInfo getMethod = property.GetGetMethod(); if (getMethod != null && getMethod.IsPublic) { return true; } MethodInfo setMethod = property.GetSetMethod(); if (setMethod != null && setMethod.IsPublic) { return true; } return false; } public static Type? GetObjectType(object? v) { return v?.GetType(); } public static string GetTypeName(Type t, TypeNameAssemblyFormatHandling assemblyFormat, ISerializationBinder? binder) { string fullyQualifiedTypeName = GetFullyQualifiedTypeName(t, binder); return assemblyFormat switch { TypeNameAssemblyFormatHandling.Simple => RemoveAssemblyDetails(fullyQualifiedTypeName), TypeNameAssemblyFormatHandling.Full => fullyQualifiedTypeName, _ => throw new ArgumentOutOfRangeException(), }; } private static string GetFullyQualifiedTypeName(Type t, ISerializationBinder? binder) { if (binder != null) { binder.BindToName(t, out string assemblyName, out string typeName); return typeName + ((assemblyName == null) ? "" : (", " + assemblyName)); } return t.AssemblyQualifiedName; } private static string RemoveAssemblyDetails(string fullyQualifiedTypeName) { StringBuilder stringBuilder = new StringBuilder(); bool flag = false; bool flag2 = false; bool flag3 = false; foreach (char c in fullyQualifiedTypeName) { switch (c) { case '[': flag = false; flag2 = false; flag3 = true; stringBuilder.Append(c); break; case ']': flag = false; flag2 = false; flag3 = false; stringBuilder.Append(c); break; case ',': if (flag3) { stringBuilder.Append(c); } else if (!flag) { flag = true; stringBuilder.Append(c); } else { flag2 = true; } break; default: flag3 = false; if (!flag2) { stringBuilder.Append(c); } break; } } return stringBuilder.ToString(); } public static bool HasDefaultConstructor(Type t, bool nonPublic) { ValidationUtils.ArgumentNotNull(t, "t"); if (t.IsValueType()) { return true; } return GetDefaultConstructor(t, nonPublic) != null; } public static ConstructorInfo? GetDefaultConstructor(Type t) { return GetDefaultConstructor(t, nonPublic: false); } public static ConstructorInfo? GetDefaultConstructor(Type t, bool nonPublic) { BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public; if (nonPublic) { bindingFlags |= BindingFlags.NonPublic; } return t.GetConstructors(bindingFlags).SingleOrDefault((ConstructorInfo c) => !c.GetParameters().Any()); } public static bool IsNullable(Type t) { ValidationUtils.ArgumentNotNull(t, "t"); if (t.IsValueType()) { return IsNullableType(t); } return true; } public static bool IsNullableType(Type t) { ValidationUtils.ArgumentNotNull(t, "t"); if (t.IsGenericType()) { return t.GetGenericTypeDefinition() == typeof(Nullable<>); } return false; } public static Type EnsureNotNullableType(Type t) { if (!IsNullableType(t)) { return t; } return Nullable.GetUnderlyingType(t); } public static Type EnsureNotByRefType(Type t) { if (!t.IsByRef || !t.HasElementType) { return t; } return t.GetElementType(); } public static bool IsGenericDefinition(Type type, Type genericInterfaceDefinition) { if (!type.IsGenericType()) { return false; } return type.GetGenericTypeDefinition() == genericInterfaceDefinition; } public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition) { Type implementingType; return ImplementsGenericDefinition(type, genericInterfaceDefinition, out implementingType); } public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, [NotNullWhen(true)] out Type? implementingType) { ValidationUtils.ArgumentNotNull(type, "type"); ValidationUtils.ArgumentNotNull(genericInterfaceDefinition, "genericInterfaceDefinition"); if (!genericInterfaceDefinition.IsInterface() || !genericInterfaceDefinition.IsGenericTypeDefinition()) { throw new ArgumentNullException("'{0}' is not a generic interface definition.".FormatWith(CultureInfo.InvariantCulture, genericInterfaceDefinition)); } if (type.IsInterface() && type.IsGenericType()) { Type genericTypeDefinition = type.GetGenericTypeDefinition(); if (genericInterfaceDefinition == genericTypeDefinition) { implementingType = type; return true; } } Type[] interfaces = type.GetInterfaces(); foreach (Type type2 in interfaces) { if (type2.IsGenericType()) { Type genericTypeDefinition2 = type2.GetGenericTypeDefinition(); if (genericInterfaceDefinition == genericTypeDefinition2) { implementingType = type2; return true; } } } implementingType = null; return false; } public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition) { Type implementingType; return InheritsGenericDefinition(type, genericClassDefinition, out implementingType); } public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type? implementingType) { ValidationUtils.ArgumentNotNull(type, "type"); ValidationUtils.ArgumentNotNull(genericClassDefinition, "genericClassDefinition"); if (!genericClassDefinition.IsClass() || !genericClassDefinition.IsGenericTypeDefinition()) { throw new ArgumentNullException("'{0}' is not a generic class definition.".FormatWith(CultureInfo.InvariantCulture, genericClassDefinition)); } return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType); } private static bool InheritsGenericDefinitionInternal(Type type, Type genericClassDefinition, out Type? implementingType) { Type type2 = type; do { if (type2.IsGenericType() && genericClassDefinition == type2.GetGenericTypeDefinition()) { implementingType = type2; return true; } type2 = type2.BaseType(); } while (type2 != null); implementingType = null; return false; } public static Type? GetCollectionItemType(Type type) { ValidationUtils.ArgumentNotNull(type, "type"); if (type.IsArray) { return type.GetElementType(); } if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out Type implementingType)) { if (implementingType.IsGenericTypeDefinition()) { throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type)); } return implementingType.GetGenericArguments()[0]; } if (typeof(IEnumerable).IsAssignableFrom(type)) { return null; } throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type)); } public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type? keyType, out Type? valueType) { ValidationUtils.ArgumentNotNull(dictionaryType, "dictionaryType"); if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<, >), out Type implementingType)) { if (implementingType.IsGenericTypeDefinition()) { throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType)); } Type[] genericArguments = implementingType.GetGenericArguments(); keyType = genericArguments[0]; valueType = genericArguments[1]; } else { if (!typeof(IDictionary).IsAssignableFrom(dictionaryType)) { throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType)); } keyType = null; valueType = null; } } public static Type GetMemberUnderlyingType(MemberInfo member) { ValidationUtils.ArgumentNotNull(member, "member"); return member.MemberType() switch { MemberTypes.Field => ((FieldInfo)member).FieldType, MemberTypes.Property => ((PropertyInfo)member).PropertyType, MemberTypes.Event => ((EventInfo)member).EventHandlerType, MemberTypes.Method => ((MethodInfo)member).ReturnType, _ => throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo, EventInfo or MethodInfo", "member"), }; } public static bool IsByRefLikeType(Type type) { if (!type.IsValueType()) { return false; } Attribute[] attributes = GetAttributes(type, null, inherit: false); for (int i = 0; i < attributes.Length; i++) { if (string.Equals(attributes[i].GetType().FullName, "System.Runtime.CompilerServices.IsByRefLikeAttribute", StringComparison.Ordinal)) { return true; } } return false; } public static bool IsIndexedProperty(PropertyInfo property) { ValidationUtils.ArgumentNotNull(property, "property"); return property.GetIndexParameters().Length != 0; } public static object? GetMemberValue(MemberInfo member, object target) { ValidationUtils.ArgumentNotNull(member, "member"); ValidationUtils.ArgumentNotNull(target, "target"); switch (member.MemberType()) { case MemberTypes.Field: return ((FieldInfo)member).GetValue(target); case MemberTypes.Property: try { return ((PropertyInfo)member).GetValue(target, null); } catch (TargetParameterCountException innerException) { throw new ArgumentException("MemberInfo '{0}' has index parameters".FormatWith(CultureInfo.InvariantCulture, member.Name), innerException); } default: throw new ArgumentException("MemberInfo '{0}' is not of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), "member"); } } public static void SetMemberValue(MemberInfo member, object target, object? value) { ValidationUtils.ArgumentNotNull(member, "member"); ValidationUtils.ArgumentNotNull(target, "target"); switch (member.MemberType()) { case MemberTypes.Field: ((FieldInfo)member).SetValue(target, value); break; case MemberTypes.Property: ((PropertyInfo)member).SetValue(target, value, null); break; default: throw new ArgumentException("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), "member"); } } public static bool CanReadMemberValue(MemberInfo member, bool nonPublic) { switch (member.MemberType()) { case MemberTypes.Field: { FieldInfo fieldInfo = (FieldInfo)member; if (nonPublic) { return true; } if (fieldInfo.IsPublic) { return true; } return false; } case MemberTypes.Property: { PropertyInfo propertyInfo = (PropertyInfo)member; if (!propertyInfo.CanRead) { return false; } if (nonPublic) { return true; } return propertyInfo.GetGetMethod(nonPublic) != null; } default: return false; } } public static bool CanSetMemberValue(MemberInfo member, bool nonPublic, bool canSetReadOnly) { switch (member.MemberType()) { case MemberTypes.Field: { FieldInfo fieldInfo = (FieldInfo)member; if (fieldInfo.IsLiteral) { return false; } if (fieldInfo.IsInitOnly && !canSetReadOnly) { return false; } if (nonPublic) { return true; } if (fieldInfo.IsPublic) { return true; } return false; } case MemberTypes.Property: { PropertyInfo propertyInfo = (PropertyInfo)member; if (!propertyInfo.CanWrite) { return false; } if (nonPublic) { return true; } return propertyInfo.GetSetMethod(nonPublic) != null; } default: return false; } } public static List GetFieldsAndProperties(Type type, BindingFlags bindingAttr) { List list = new List(); list.AddRange(GetFields(type, bindingAttr)); list.AddRange(GetProperties(type, bindingAttr)); List list2 = new List(list.Count); foreach (IGrouping item in from m in list group m by m.Name) { if (item.Count() == 1) { list2.Add(item.First()); continue; } List list3 = new List(); foreach (MemberInfo memberInfo in item) { if (list3.Count == 0) { list3.Add(memberInfo); } else if ((!IsOverridenGenericMember(memberInfo, bindingAttr) || memberInfo.Name == "Item") && !list3.Any((MemberInfo m) => m.DeclaringType == memberInfo.DeclaringType)) { list3.Add(memberInfo); } } list2.AddRange(list3); } return list2; } private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr) { if (memberInfo.MemberType() != MemberTypes.Property) { return false; } PropertyInfo propertyInfo = (PropertyInfo)memberInfo; if (!propertyInfo.IsVirtual()) { return false; } Type declaringType = propertyInfo.DeclaringType; if (!declaringType.IsGenericType()) { return false; } Type genericTypeDefinition = declaringType.GetGenericTypeDefinition(); if (genericTypeDefinition == null) { return false; } MemberInfo[] member = genericTypeDefinition.GetMember(propertyInfo.Name, bindingAttr); if (member.Length == 0) { return false; } if (!GetMemberUnderlyingType(member[0]).IsGenericParameter) { return false; } return true; } public static T? GetAttribute(object attributeProvider) where T : Attribute { return GetAttribute(attributeProvider, inherit: true); } public static T? GetAttribute(object attributeProvider, bool inherit) where T : Attribute { T[] attributes = GetAttributes(attributeProvider, inherit); if (attributes == null) { return null; } return attributes.FirstOrDefault(); } public static T[] GetAttributes(object attributeProvider, bool inherit) where T : Attribute { Attribute[] attributes = GetAttributes(attributeProvider, typeof(T), inherit); if (attributes is T[] result) { return result; } return attributes.Cast().ToArray(); } public static Attribute[] GetAttributes(object attributeProvider, Type? attributeType, bool inherit) { ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider"); if (!(attributeProvider is Type type)) { if (!(attributeProvider is Assembly element)) { if (!(attributeProvider is MemberInfo element2)) { if (!(attributeProvider is Module element3)) { if (attributeProvider is ParameterInfo element4) { if (!(attributeType != null)) { return Attribute.GetCustomAttributes(element4, inherit); } return Attribute.GetCustomAttributes(element4, attributeType, inherit); } ICustomAttributeProvider customAttributeProvider = (ICustomAttributeProvider)attributeProvider; return (Attribute[])((attributeType != null) ? customAttributeProvider.GetCustomAttributes(attributeType, inherit) : customAttributeProvider.GetCustomAttributes(inherit)); } if (!(attributeType != null)) { return Attribute.GetCustomAttributes(element3, inherit); } return Attribute.GetCustomAttributes(element3, attributeType, inherit); } if (!(attributeType != null)) { return Attribute.GetCustomAttributes(element2, inherit); } return Attribute.GetCustomAttributes(element2, attributeType, inherit); } if (!(attributeType != null)) { return Attribute.GetCustomAttributes(element); } return Attribute.GetCustomAttributes(element, attributeType); } return ((attributeType != null) ? type.GetCustomAttributes(attributeType, inherit) : type.GetCustomAttributes(inherit)).Cast().ToArray(); } public static StructMultiKey SplitFullyQualifiedTypeName(string fullyQualifiedTypeName) { int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName); string v; string v2; if (assemblyDelimiterIndex.HasValue) { v = fullyQualifiedTypeName.Trim(0, assemblyDelimiterIndex.GetValueOrDefault()); v2 = fullyQualifiedTypeName.Trim(assemblyDelimiterIndex.GetValueOrDefault() + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.GetValueOrDefault() - 1); } else { v = fullyQualifiedTypeName; v2 = null; } return new StructMultiKey(v2, v); } private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName) { int num = 0; for (int i = 0; i < fullyQualifiedTypeName.Length; i++) { switch (fullyQualifiedTypeName[i]) { case '[': num++; break; case ']': num--; break; case ',': if (num == 0) { return i; } break; } } return null; } public static MemberInfo? GetMemberInfoFromType(Type targetType, MemberInfo memberInfo) { if (memberInfo.MemberType() == MemberTypes.Property) { PropertyInfo propertyInfo = (PropertyInfo)memberInfo; Type[] types = (from p in propertyInfo.GetIndexParameters() select p.ParameterType).ToArray(); return targetType.GetProperty(propertyInfo.Name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, propertyInfo.PropertyType, types, null); } return targetType.GetMember(memberInfo.Name, memberInfo.MemberType(), BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).SingleOrDefault(); } public static IEnumerable GetFields(Type targetType, BindingFlags bindingAttr) { ValidationUtils.ArgumentNotNull(targetType, "targetType"); List list = new List(targetType.GetFields(bindingAttr)); GetChildPrivateFields(list, targetType, bindingAttr); return list.Cast(); } private static void GetChildPrivateFields(IList initialFields, Type type, BindingFlags bindingAttr) { Type type2 = type; if ((bindingAttr & BindingFlags.NonPublic) == 0) { return; } BindingFlags bindingAttr2 = bindingAttr.RemoveFlag(BindingFlags.Public); while ((type2 = type2.BaseType()) != null) { IEnumerable collection = from f in type2.GetFields(bindingAttr2) where f.IsPrivate select f; initialFields.AddRange(collection); } } public static IEnumerable GetProperties(Type targetType, BindingFlags bindingAttr) { ValidationUtils.ArgumentNotNull(targetType, "targetType"); List list = new List(targetType.GetProperties(bindingAttr)); if (targetType.IsInterface()) { Type[] interfaces = targetType.GetInterfaces(); foreach (Type type in interfaces) { list.AddRange(type.GetProperties(bindingAttr)); } } GetChildPrivateProperties(list, targetType, bindingAttr); for (int j = 0; j < list.Count; j++) { PropertyInfo propertyInfo = list[j]; if (propertyInfo.DeclaringType != targetType) { PropertyInfo value = (PropertyInfo)GetMemberInfoFromType(propertyInfo.DeclaringType, propertyInfo); list[j] = value; } } return list; } public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag) { if ((bindingAttr & flag) != flag) { return bindingAttr; } return bindingAttr ^ flag; } private static void GetChildPrivateProperties(IList initialProperties, Type type, BindingFlags bindingAttr) { Type type2 = type; while ((type2 = type2.BaseType()) != null) { PropertyInfo[] properties = type2.GetProperties(bindingAttr); foreach (PropertyInfo propertyInfo in properties) { PropertyInfo subTypeProperty = propertyInfo; if (!subTypeProperty.IsVirtual()) { if (!IsPublic(subTypeProperty)) { int num = initialProperties.IndexOf((PropertyInfo p) => p.Name == subTypeProperty.Name); if (num == -1) { initialProperties.Add(subTypeProperty); } else if (!IsPublic(initialProperties[num])) { initialProperties[num] = subTypeProperty; } } else if (initialProperties.IndexOf((PropertyInfo p) => p.Name == subTypeProperty.Name && p.DeclaringType == subTypeProperty.DeclaringType) == -1) { initialProperties.Add(subTypeProperty); } } else { Type subTypePropertyDeclaringType = subTypeProperty.GetBaseDefinition()?.DeclaringType ?? subTypeProperty.DeclaringType; if (initialProperties.IndexOf((PropertyInfo p) => p.Name == subTypeProperty.Name && p.IsVirtual() && (p.GetBaseDefinition()?.DeclaringType ?? p.DeclaringType).IsAssignableFrom(subTypePropertyDeclaringType)) == -1) { initialProperties.Add(subTypeProperty); } } } } } public static bool IsMethodOverridden(Type currentType, Type methodDeclaringType, string method) { string method2 = method; Type methodDeclaringType2 = methodDeclaringType; return currentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Any((MethodInfo info) => info.Name == method2 && info.DeclaringType != methodDeclaringType2 && info.GetBaseDefinition().DeclaringType == methodDeclaringType2); } public static object? GetDefaultValue(Type type) { if (!type.IsValueType()) { return null; } switch (ConvertUtils.GetTypeCode(type)) { case PrimitiveTypeCode.Boolean: return false; case PrimitiveTypeCode.Char: case PrimitiveTypeCode.SByte: case PrimitiveTypeCode.Int16: case PrimitiveTypeCode.UInt16: case PrimitiveTypeCode.Int32: case PrimitiveTypeCode.Byte: case PrimitiveTypeCode.UInt32: return 0; case PrimitiveTypeCode.Int64: case PrimitiveTypeCode.UInt64: return 0L; case PrimitiveTypeCode.Single: return 0f; case PrimitiveTypeCode.Double: return 0.0; case PrimitiveTypeCode.Decimal: return 0m; case PrimitiveTypeCode.DateTime: return default(DateTime); case PrimitiveTypeCode.BigInteger: return default(BigInteger); case PrimitiveTypeCode.Guid: return default(Guid); case PrimitiveTypeCode.DateTimeOffset: return default(DateTimeOffset); default: if (IsNullable(type)) { return null; } return Activator.CreateInstance(type); } } } internal struct StringBuffer { private char[]? _buffer; private int _position; public int Position { get { return _position; } set { _position = value; } } public bool IsEmpty => _buffer == null; public char[]? InternalBuffer => _buffer; public StringBuffer(IArrayPool? bufferPool, int initalSize) : this(BufferUtils.RentBuffer(bufferPool, initalSize)) { } private StringBuffer(char[] buffer) { _buffer = buffer; _position = 0; } public void Append(IArrayPool? bufferPool, char value) { if (_position == _buffer.Length) { EnsureSize(bufferPool, 1); } _buffer[_position++] = value; } public void Append(IArrayPool? bufferPool, char[] buffer, int startIndex, int count) { if (_position + count >= _buffer.Length) { EnsureSize(bufferPool, count); } Array.Copy(buffer, startIndex, _buffer, _position, count); _position += count; } public void Clear(IArrayPool? bufferPool) { if (_buffer != null) { BufferUtils.ReturnBuffer(bufferPool, _buffer); _buffer = null; } _position = 0; } private void EnsureSize(IArrayPool? bufferPool, int appendLength) { char[] array = BufferUtils.RentBuffer(bufferPool, (_position + appendLength) * 2); if (_buffer != null) { Array.Copy(_buffer, array, _position); BufferUtils.ReturnBuffer(bufferPool, _buffer); } _buffer = array; } public override string ToString() { return ToString(0, _position); } public string ToString(int start, int length) { return new string(_buffer, start, length); } } internal readonly struct StringReference { private readonly char[] _chars; private readonly int _startIndex; private readonly int _length; public char this[int i] => _chars[i]; public char[] Chars => _chars; public int StartIndex => _startIndex; public int Length => _length; public StringReference(char[] chars, int startIndex, int length) { _chars = chars; _startIndex = startIndex; _length = length; } public override string ToString() { return new string(_chars, _startIndex, _length); } } internal static class StringReferenceExtensions { public static int IndexOf(this StringReference s, char c, int startIndex, int length) { int num = Array.IndexOf(s.Chars, c, s.StartIndex + startIndex, length); if (num == -1) { return -1; } return num - s.StartIndex; } public static bool StartsWith(this StringReference s, string text) { if (text.Length > s.Length) { return false; } char[] chars = s.Chars; for (int i = 0; i < text.Length; i++) { if (text[i] != chars[i + s.StartIndex]) { return false; } } return true; } public static bool EndsWith(this StringReference s, string text) { if (text.Length > s.Length) { return false; } char[] chars = s.Chars; int num = s.StartIndex + s.Length - text.Length; for (int i = 0; i < text.Length; i++) { if (text[i] != chars[i + num]) { return false; } } return true; } } internal static class StringUtils { private enum SeparatedCaseState { Start, Lower, Upper, NewWord } public const string CarriageReturnLineFeed = "\r\n"; public const string Empty = ""; public const char CarriageReturn = '\r'; public const char LineFeed = '\n'; public const char Tab = '\t'; public static bool IsNullOrEmpty([NotNullWhen(false)] string? value) { return string.IsNullOrEmpty(value); } public static string FormatWith(this string format, IFormatProvider provider, object? arg0) { return format.FormatWith(provider, new object[1] { arg0 }); } public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1) { return format.FormatWith(provider, new object[2] { arg0, arg1 }); } public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1, object? arg2) { return format.FormatWith(provider, new object[3] { arg0, arg1, arg2 }); } public static string FormatWith(this string format, IFormatProvider provider, object? arg0, object? arg1, object? arg2, object? arg3) { return format.FormatWith(provider, new object[4] { arg0, arg1, arg2, arg3 }); } private static string FormatWith(this string format, IFormatProvider provider, params object?[] args) { ValidationUtils.ArgumentNotNull(format, "format"); return string.Format(provider, format, args); } public static bool IsWhiteSpace(string s) { if (s == null) { throw new ArgumentNullException("s"); } if (s.Length == 0) { return false; } for (int i = 0; i < s.Length; i++) { if (!char.IsWhiteSpace(s[i])) { return false; } } return true; } public static StringWriter CreateStringWriter(int capacity) { return new StringWriter(new StringBuilder(capacity), CultureInfo.InvariantCulture); } public static void ToCharAsUnicode(char c, char[] buffer) { buffer[0] = '\\'; buffer[1] = 'u'; buffer[2] = MathUtils.IntToHex(((int)c >> 12) & 0xF); buffer[3] = MathUtils.IntToHex(((int)c >> 8) & 0xF); buffer[4] = MathUtils.IntToHex(((int)c >> 4) & 0xF); buffer[5] = MathUtils.IntToHex(c & 0xF); } public static TSource? ForgivingCaseSensitiveFind(this IEnumerable source, Func valueSelector, string testValue) { Func valueSelector2 = valueSelector; string testValue2 = testValue; if (source == null) { throw new ArgumentNullException("source"); } if (valueSelector2 == null) { throw new ArgumentNullException("valueSelector"); } IEnumerable source2 = source.Where((TSource s) => string.Equals(valueSelector2(s), testValue2, StringComparison.OrdinalIgnoreCase)); if (source2.Count() <= 1) { return source2.SingleOrDefault(); } return source.Where((TSource s) => string.Equals(valueSelector2(s), testValue2, StringComparison.Ordinal)).SingleOrDefault(); } public static string ToCamelCase(string s) { if (IsNullOrEmpty(s) || !char.IsUpper(s[0])) { return s; } char[] array = s.ToCharArray(); for (int i = 0; i < array.Length && (i != 1 || char.IsUpper(array[i])); i++) { bool flag = i + 1 < array.Length; if (i > 0 && flag && !char.IsUpper(array[i + 1])) { if (char.IsSeparator(array[i + 1])) { array[i] = ToLower(array[i]); } break; } array[i] = ToLower(array[i]); } return new string(array); } private static char ToLower(char c) { c = char.ToLower(c, CultureInfo.InvariantCulture); return c; } public static string ToSnakeCase(string s) { return ToSeparatedCase(s, '_'); } public static string ToKebabCase(string s) { return ToSeparatedCase(s, '-'); } private static string ToSeparatedCase(string s, char separator) { if (IsNullOrEmpty(s)) { return s; } StringBuilder stringBuilder = new StringBuilder(); SeparatedCaseState separatedCaseState = SeparatedCaseState.Start; for (int i = 0; i < s.Length; i++) { if (s[i] == ' ') { if (separatedCaseState != 0) { separatedCaseState = SeparatedCaseState.NewWord; } } else if (char.IsUpper(s[i])) { switch (separatedCaseState) { case SeparatedCaseState.Upper: { bool flag = i + 1 < s.Length; if (i > 0 && flag) { char c = s[i + 1]; if (!char.IsUpper(c) && c != separator) { stringBuilder.Append(separator); } } break; } case SeparatedCaseState.Lower: case SeparatedCaseState.NewWord: stringBuilder.Append(separator); break; } char value = char.ToLower(s[i], CultureInfo.InvariantCulture); stringBuilder.Append(value); separatedCaseState = SeparatedCaseState.Upper; } else if (s[i] == separator) { stringBuilder.Append(separator); separatedCaseState = SeparatedCaseState.Start; } else { if (separatedCaseState == SeparatedCaseState.NewWord) { stringBuilder.Append(separator); } stringBuilder.Append(s[i]); separatedCaseState = SeparatedCaseState.Lower; } } return stringBuilder.ToString(); } public static bool IsHighSurrogate(char c) { return char.IsHighSurrogate(c); } public static bool IsLowSurrogate(char c) { return char.IsLowSurrogate(c); } public static int IndexOf(string s, char c) { return s.IndexOf(c); } public static string Replace(string s, string oldValue, string newValue) { return s.Replace(oldValue, newValue); } public static bool StartsWith(this string source, char value) { if (source.Length > 0) { return source[0] == value; } return false; } public static bool EndsWith(this string source, char value) { if (source.Length > 0) { return source[source.Length - 1] == value; } return false; } public static string Trim(this string s, int start, int length) { if (s == null) { throw new ArgumentNullException(); } if (start < 0) { throw new ArgumentOutOfRangeException("start"); } if (length < 0) { throw new ArgumentOutOfRangeException("length"); } int num = start + length - 1; if (num >= s.Length) { throw new ArgumentOutOfRangeException("length"); } while (start < num && char.IsWhiteSpace(s[start])) { start++; } while (num >= start && char.IsWhiteSpace(s[num])) { num--; } return s.Substring(start, num - start + 1); } } internal readonly struct StructMultiKey : IEquatable> { public readonly T1 Value1; public readonly T2 Value2; public StructMultiKey(T1 v1, T2 v2) { Value1 = v1; Value2 = v2; } public override int GetHashCode() { T1 value = Value1; int num = ((value != null) ? value.GetHashCode() : 0); T2 value2 = Value2; return num ^ ((value2 != null) ? value2.GetHashCode() : 0); } public override bool Equals(object? obj) { if (!(obj is StructMultiKey other)) { return false; } return Equals(other); } public bool Equals(StructMultiKey other) { if (object.Equals(Value1, other.Value1)) { return object.Equals(Value2, other.Value2); } return false; } } internal class ThreadSafeStore where TKey : notnull { private readonly ConcurrentDictionary _concurrentStore; private readonly Func _creator; public ThreadSafeStore(Func creator) { ValidationUtils.ArgumentNotNull(creator, "creator"); _creator = creator; _concurrentStore = new ConcurrentDictionary(); } public TValue Get(TKey key) { return _concurrentStore.GetOrAdd(key, _creator); } } internal static class TypeExtensions { public static MethodInfo Method(this Delegate d) { return d.Method; } public static MemberTypes MemberType(this MemberInfo memberInfo) { return memberInfo.MemberType; } public static bool ContainsGenericParameters(this Type type) { return type.ContainsGenericParameters; } public static bool IsInterface(this Type type) { return type.IsInterface; } public static bool IsGenericType(this Type type) { return type.IsGenericType; } public static bool IsGenericTypeDefinition(this Type type) { return type.IsGenericTypeDefinition; } public static Type? BaseType(this Type type) { return type.BaseType; } public static Assembly Assembly(this Type type) { return type.Assembly; } public static bool IsEnum(this Type type) { return type.IsEnum; } public static bool IsClass(this Type type) { return type.IsClass; } public static bool IsSealed(this Type type) { return type.IsSealed; } public static bool IsAbstract(this Type type) { return type.IsAbstract; } public static bool IsVisible(this Type type) { return type.IsVisible; } public static bool IsValueType(this Type type) { return type.IsValueType; } public static bool IsPrimitive(this Type type) { return type.IsPrimitive; } public static bool AssignableToTypeName(this Type type, string fullTypeName, bool searchInterfaces, [NotNullWhen(true)] out Type? match) { Type type2 = type; while (type2 != null) { if (string.Equals(type2.FullName, fullTypeName, StringComparison.Ordinal)) { match = type2; return true; } type2 = type2.BaseType(); } if (searchInterfaces) { Type[] interfaces = type.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { if (string.Equals(interfaces[i].Name, fullTypeName, StringComparison.Ordinal)) { match = type; return true; } } } match = null; return false; } public static bool AssignableToTypeName(this Type type, string fullTypeName, bool searchInterfaces) { Type match; return type.AssignableToTypeName(fullTypeName, searchInterfaces, out match); } public static bool ImplementInterface(this Type type, Type interfaceType) { Type type2 = type; while (type2 != null) { foreach (Type item in (IEnumerable)type2.GetInterfaces()) { if (item == interfaceType || (item != null && item.ImplementInterface(interfaceType))) { return true; } } type2 = type2.BaseType(); } return false; } } internal static class ValidationUtils { public static void ArgumentNotNull([NotNull] object? value, string parameterName) { if (value == null) { throw new ArgumentNullException(parameterName); } } } } namespace Newtonsoft.Json.Serialization { internal static class CachedAttributeGetter where T : Attribute { private static readonly ThreadSafeStore TypeAttributeCache = new ThreadSafeStore(JsonTypeReflector.GetAttribute); public static T? GetAttribute(object type) { return TypeAttributeCache.Get(type); } } internal class CamelCaseNamingStrategy : NamingStrategy { public CamelCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) { base.ProcessDictionaryKeys = processDictionaryKeys; base.OverrideSpecifiedNames = overrideSpecifiedNames; } public CamelCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) : this(processDictionaryKeys, overrideSpecifiedNames) { base.ProcessExtensionDataNames = processExtensionDataNames; } public CamelCaseNamingStrategy() { } protected override string ResolvePropertyName(string name) { return StringUtils.ToCamelCase(name); } } internal class CamelCasePropertyNamesContractResolver : DefaultContractResolver { private static readonly object TypeContractCacheLock = new object(); private static readonly DefaultJsonNameTable NameTable = new DefaultJsonNameTable(); private static Dictionary, JsonContract>? _contractCache; public CamelCasePropertyNamesContractResolver() { base.NamingStrategy = new CamelCaseNamingStrategy { ProcessDictionaryKeys = true, OverrideSpecifiedNames = true }; } public override JsonContract ResolveContract(Type type) { if (type == null) { throw new ArgumentNullException("type"); } StructMultiKey key = new StructMultiKey(GetType(), type); Dictionary, JsonContract> contractCache = _contractCache; if (contractCache == null || !contractCache.TryGetValue(key, out var value)) { value = CreateContract(type); lock (TypeContractCacheLock) { contractCache = _contractCache; Dictionary, JsonContract> obj = ((contractCache != null) ? new Dictionary, JsonContract>(contractCache) : new Dictionary, JsonContract>()); obj[key] = value; _contractCache = obj; } } return value; } internal override DefaultJsonNameTable GetNameTable() { return NameTable; } } internal class DefaultContractResolver : IContractResolver { internal class EnumerableDictionaryWrapper : IEnumerable>, IEnumerable { private readonly IEnumerable> _e; public EnumerableDictionaryWrapper(IEnumerable> e) { ValidationUtils.ArgumentNotNull(e, "e"); _e = e; } public IEnumerator> GetEnumerator() { foreach (KeyValuePair item in _e) { yield return new KeyValuePair(item.Key, item.Value); } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } private static readonly IContractResolver _instance = new DefaultContractResolver(); private static readonly string[] BlacklistedTypeNames = new string[3] { "System.IO.DriveInfo", "System.IO.FileInfo", "System.IO.DirectoryInfo" }; private static readonly JsonConverter[] BuiltInConverters = new JsonConverter[10] { new EntityKeyMemberConverter(), new ExpandoObjectConverter(), new XmlNodeConverter(), new BinaryConverter(), new DataSetConverter(), new DataTableConverter(), new DiscriminatedUnionConverter(), new KeyValuePairConverter(), new BsonObjectIdConverter(), new RegexConverter() }; private readonly DefaultJsonNameTable _nameTable = new DefaultJsonNameTable(); private readonly ThreadSafeStore _contractCache; internal static IContractResolver Instance => _instance; public bool DynamicCodeGeneration => JsonTypeReflector.DynamicCodeGeneration; [Obsolete("DefaultMembersSearchFlags is obsolete. To modify the members serialized inherit from DefaultContractResolver and override the GetSerializableMembers method instead.")] public BindingFlags DefaultMembersSearchFlags { get; set; } public bool SerializeCompilerGeneratedMembers { get; set; } public bool IgnoreSerializableInterface { get; set; } public bool IgnoreSerializableAttribute { get; set; } public bool IgnoreIsSpecifiedMembers { get; set; } public bool IgnoreShouldSerializeMembers { get; set; } public NamingStrategy? NamingStrategy { get; set; } public DefaultContractResolver() { IgnoreSerializableAttribute = true; DefaultMembersSearchFlags = BindingFlags.Instance | BindingFlags.Public; _contractCache = new ThreadSafeStore(CreateContract); } public virtual JsonContract ResolveContract(Type type) { ValidationUtils.ArgumentNotNull(type, "type"); return _contractCache.Get(type); } private static bool FilterMembers(MemberInfo member) { if (member is PropertyInfo propertyInfo) { if (ReflectionUtils.IsIndexedProperty(propertyInfo)) { return false; } return !ReflectionUtils.IsByRefLikeType(propertyInfo.PropertyType); } if (member is FieldInfo fieldInfo) { return !ReflectionUtils.IsByRefLikeType(fieldInfo.FieldType); } return true; } protected virtual List GetSerializableMembers(Type objectType) { bool ignoreSerializableAttribute = IgnoreSerializableAttribute; MemberSerialization objectMemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType, ignoreSerializableAttribute); IEnumerable enumerable = from m in ReflectionUtils.GetFieldsAndProperties(objectType, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) where !(m is PropertyInfo property) || !ReflectionUtils.IsIndexedProperty(property) select m; List list = new List(); if (objectMemberSerialization != MemberSerialization.Fields) { DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType); List list2 = ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags).Where(FilterMembers).ToList(); foreach (MemberInfo item in enumerable) { if (SerializeCompilerGeneratedMembers || !item.IsDefined(typeof(CompilerGeneratedAttribute), inherit: true)) { if (list2.Contains(item)) { list.Add(item); } else if (JsonTypeReflector.GetAttribute(item) != null) { list.Add(item); } else if (JsonTypeReflector.GetAttribute(item) != null) { list.Add(item); } else if (dataContractAttribute != null && JsonTypeReflector.GetAttribute(item) != null) { list.Add(item); } else if (objectMemberSerialization == MemberSerialization.Fields && item.MemberType() == MemberTypes.Field) { list.Add(item); } } } if (objectType.AssignableToTypeName("System.Data.Objects.DataClasses.EntityObject", searchInterfaces: false, out Type _)) { list = list.Where(ShouldSerializeEntityMember).ToList(); } if (typeof(Exception).IsAssignableFrom(objectType)) { list = list.Where((MemberInfo m) => !string.Equals(m.Name, "TargetSite", StringComparison.Ordinal)).ToList(); } } else { foreach (MemberInfo item2 in enumerable) { if (item2 is FieldInfo fieldInfo && !fieldInfo.IsStatic) { list.Add(item2); } } } return list; } private bool ShouldSerializeEntityMember(MemberInfo memberInfo) { if (memberInfo is PropertyInfo propertyInfo && propertyInfo.PropertyType.IsGenericType() && propertyInfo.PropertyType.GetGenericTypeDefinition().FullName == "System.Data.Objects.DataClasses.EntityReference`1") { return false; } return true; } protected virtual JsonObjectContract CreateObjectContract(Type objectType) { JsonObjectContract jsonObjectContract = new JsonObjectContract(objectType); InitializeContract(jsonObjectContract); bool ignoreSerializableAttribute = IgnoreSerializableAttribute; jsonObjectContract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(jsonObjectContract.NonNullableUnderlyingType, ignoreSerializableAttribute); jsonObjectContract.Properties.AddRange(CreateProperties(jsonObjectContract.NonNullableUnderlyingType, jsonObjectContract.MemberSerialization)); Func func = null; JsonObjectAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(jsonObjectContract.NonNullableUnderlyingType); if (cachedAttribute != null) { jsonObjectContract.ItemRequired = cachedAttribute._itemRequired; jsonObjectContract.ItemNullValueHandling = cachedAttribute._itemNullValueHandling; jsonObjectContract.MissingMemberHandling = cachedAttribute._missingMemberHandling; if (cachedAttribute.NamingStrategyType != null) { NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(cachedAttribute); func = (string s) => namingStrategy.GetDictionaryKey(s); } } if (func == null) { func = ResolveExtensionDataName; } jsonObjectContract.ExtensionDataNameResolver = func; if (jsonObjectContract.IsInstantiable) { ConstructorInfo attributeConstructor = GetAttributeConstructor(jsonObjectContract.NonNullableUnderlyingType); if (attributeConstructor != null) { jsonObjectContract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(attributeConstructor); jsonObjectContract.CreatorParameters.AddRange(CreateConstructorParameters(attributeConstructor, jsonObjectContract.Properties)); } else if (jsonObjectContract.MemberSerialization == MemberSerialization.Fields) { if (JsonTypeReflector.FullyTrusted) { jsonObjectContract.DefaultCreator = jsonObjectContract.GetUninitializedObject; } } else if (jsonObjectContract.DefaultCreator == null || jsonObjectContract.DefaultCreatorNonPublic) { ConstructorInfo parameterizedConstructor = GetParameterizedConstructor(jsonObjectContract.NonNullableUnderlyingType); if (parameterizedConstructor != null) { jsonObjectContract.ParameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(parameterizedConstructor); jsonObjectContract.CreatorParameters.AddRange(CreateConstructorParameters(parameterizedConstructor, jsonObjectContract.Properties)); } } else if (jsonObjectContract.NonNullableUnderlyingType.IsValueType()) { ConstructorInfo immutableConstructor = GetImmutableConstructor(jsonObjectContract.NonNullableUnderlyingType, jsonObjectContract.Properties); if (immutableConstructor != null) { jsonObjectContract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(immutableConstructor); jsonObjectContract.CreatorParameters.AddRange(CreateConstructorParameters(immutableConstructor, jsonObjectContract.Properties)); } } } MemberInfo extensionDataMemberForType = GetExtensionDataMemberForType(jsonObjectContract.NonNullableUnderlyingType); if (extensionDataMemberForType != null) { SetExtensionDataDelegates(jsonObjectContract, extensionDataMemberForType); } if (Array.IndexOf(BlacklistedTypeNames, objectType.FullName) != -1) { jsonObjectContract.OnSerializingCallbacks.Add(ThrowUnableToSerializeError); } return jsonObjectContract; } private static void ThrowUnableToSerializeError(object o, StreamingContext context) { throw new JsonSerializationException("Unable to serialize instance of '{0}'.".FormatWith(CultureInfo.InvariantCulture, o.GetType())); } private MemberInfo? GetExtensionDataMemberForType(Type type) { return GetClassHierarchyForType(type).SelectMany(delegate(Type baseType) { List list = new List(); CollectionUtils.AddRange(list, baseType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); CollectionUtils.AddRange(list, baseType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)); return list; }).LastOrDefault(delegate(MemberInfo m) { MemberTypes memberTypes = m.MemberType(); if (memberTypes != MemberTypes.Property && memberTypes != MemberTypes.Field) { return false; } if (!m.IsDefined(typeof(JsonExtensionDataAttribute), inherit: false)) { return false; } if (!ReflectionUtils.CanReadMemberValue(m, nonPublic: true)) { throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' must have a getter.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name)); } if (ReflectionUtils.ImplementsGenericDefinition(ReflectionUtils.GetMemberUnderlyingType(m), typeof(IDictionary<, >), out Type implementingType)) { Type obj = implementingType.GetGenericArguments()[0]; Type type2 = implementingType.GetGenericArguments()[1]; if (obj.IsAssignableFrom(typeof(string)) && type2.IsAssignableFrom(typeof(JToken))) { return true; } } throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' type must implement IDictionary.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name)); }); } private static void SetExtensionDataDelegates(JsonObjectContract contract, MemberInfo member) { MemberInfo member2 = member; JsonExtensionDataAttribute attribute = ReflectionUtils.GetAttribute(member2); if (attribute == null) { return; } Type memberUnderlyingType = ReflectionUtils.GetMemberUnderlyingType(member2); ReflectionUtils.ImplementsGenericDefinition(memberUnderlyingType, typeof(IDictionary<, >), out Type implementingType); Type type = implementingType.GetGenericArguments()[0]; Type type2 = implementingType.GetGenericArguments()[1]; Type type3 = ((!ReflectionUtils.IsGenericDefinition(memberUnderlyingType, typeof(IDictionary<, >))) ? memberUnderlyingType : typeof(Dictionary<, >).MakeGenericType(type, type2)); Func getExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(member2); if (attribute.ReadData) { Action setExtensionDataDictionary = (ReflectionUtils.CanSetMemberValue(member2, nonPublic: true, canSetReadOnly: false) ? JsonTypeReflector.ReflectionDelegateFactory.CreateSet(member2) : null); Func createExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(type3); MethodInfo methodInfo = memberUnderlyingType.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public, null, type2, new Type[1] { type }, null)?.GetSetMethod(); if (methodInfo == null) { methodInfo = implementingType.GetProperty("Item", BindingFlags.Instance | BindingFlags.Public, null, type2, new Type[1] { type }, null)?.GetSetMethod(); } MethodCall setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(methodInfo); ExtensionDataSetter extensionDataSetter = delegate(object o, string key, object? value) { object obj2 = getExtensionDataDictionary(o); if (obj2 == null) { if (setExtensionDataDictionary == null) { throw new JsonSerializationException("Cannot set value onto extension data member '{0}'. The extension data collection is null and it cannot be set.".FormatWith(CultureInfo.InvariantCulture, member2.Name)); } obj2 = createExtensionDataDictionary(); setExtensionDataDictionary(o, obj2); } setExtensionDataDictionaryValue(obj2, key, value); }; contract.ExtensionDataSetter = extensionDataSetter; } if (attribute.WriteData) { ConstructorInfo method = typeof(EnumerableDictionaryWrapper<, >).MakeGenericType(type, type2).GetConstructors().First(); ObjectConstructor createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(method); ExtensionDataGetter extensionDataGetter = delegate(object o) { object obj = getExtensionDataDictionary(o); return (obj == null) ? null : ((IEnumerable>)createEnumerableWrapper(obj)); }; contract.ExtensionDataGetter = extensionDataGetter; } contract.ExtensionDataValueType = type2; } private ConstructorInfo? GetAttributeConstructor(Type objectType) { IEnumerator enumerator = (from c in objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where c.IsDefined(typeof(JsonConstructorAttribute), inherit: true) select c).GetEnumerator(); if (enumerator.MoveNext()) { ConstructorInfo current = enumerator.Current; if (enumerator.MoveNext()) { throw new JsonException("Multiple constructors with the JsonConstructorAttribute."); } return current; } if (objectType == typeof(Version)) { return objectType.GetConstructor(new Type[4] { typeof(int), typeof(int), typeof(int), typeof(int) }); } return null; } private ConstructorInfo? GetImmutableConstructor(Type objectType, JsonPropertyCollection memberProperties) { IEnumerator enumerator = ((IEnumerable)objectType.GetConstructors()).GetEnumerator(); if (enumerator.MoveNext()) { ConstructorInfo current = enumerator.Current; if (!enumerator.MoveNext()) { ParameterInfo[] parameters = current.GetParameters(); if (parameters.Length != 0) { ParameterInfo[] array = parameters; foreach (ParameterInfo parameterInfo in array) { JsonProperty jsonProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); if (jsonProperty == null || jsonProperty.Writable) { return null; } } return current; } } } return null; } private ConstructorInfo? GetParameterizedConstructor(Type objectType) { ConstructorInfo[] constructors = objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public); if (constructors.Length == 1) { return constructors[0]; } return null; } protected virtual IList CreateConstructorParameters(ConstructorInfo constructor, JsonPropertyCollection memberProperties) { ParameterInfo[] parameters = constructor.GetParameters(); JsonPropertyCollection jsonPropertyCollection = new JsonPropertyCollection(constructor.DeclaringType); ParameterInfo[] array = parameters; foreach (ParameterInfo parameterInfo in array) { if (parameterInfo.Name == null) { continue; } JsonProperty jsonProperty = MatchProperty(memberProperties, parameterInfo.Name, parameterInfo.ParameterType); if (jsonProperty != null || parameterInfo.Name != null) { JsonProperty jsonProperty2 = CreatePropertyFromConstructorParameter(jsonProperty, parameterInfo); if (jsonProperty2 != null) { jsonPropertyCollection.AddProperty(jsonProperty2); } } } return jsonPropertyCollection; } private JsonProperty? MatchProperty(JsonPropertyCollection properties, string name, Type type) { if (name == null) { return null; } JsonProperty closestMatchProperty = properties.GetClosestMatchProperty(name); if (closestMatchProperty == null || closestMatchProperty.PropertyType != type) { return null; } return closestMatchProperty; } protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProperty? matchingMemberProperty, ParameterInfo parameterInfo) { JsonProperty jsonProperty = new JsonProperty(); jsonProperty.PropertyType = parameterInfo.ParameterType; jsonProperty.AttributeProvider = new ReflectionAttributeProvider(parameterInfo); SetPropertySettingsFromAttributes(jsonProperty, parameterInfo, parameterInfo.Name, parameterInfo.Member.DeclaringType, MemberSerialization.OptOut, out var _); jsonProperty.Readable = false; jsonProperty.Writable = true; if (matchingMemberProperty != null) { jsonProperty.PropertyName = ((jsonProperty.PropertyName != parameterInfo.Name) ? jsonProperty.PropertyName : matchingMemberProperty.PropertyName); jsonProperty.Converter = jsonProperty.Converter ?? matchingMemberProperty.Converter; if (!jsonProperty._hasExplicitDefaultValue && matchingMemberProperty._hasExplicitDefaultValue) { jsonProperty.DefaultValue = matchingMemberProperty.DefaultValue; } jsonProperty._required = jsonProperty._required ?? matchingMemberProperty._required; jsonProperty.IsReference = jsonProperty.IsReference ?? matchingMemberProperty.IsReference; jsonProperty.NullValueHandling = jsonProperty.NullValueHandling ?? matchingMemberProperty.NullValueHandling; jsonProperty.DefaultValueHandling = jsonProperty.DefaultValueHandling ?? matchingMemberProperty.DefaultValueHandling; jsonProperty.ReferenceLoopHandling = jsonProperty.ReferenceLoopHandling ?? matchingMemberProperty.ReferenceLoopHandling; jsonProperty.ObjectCreationHandling = jsonProperty.ObjectCreationHandling ?? matchingMemberProperty.ObjectCreationHandling; jsonProperty.TypeNameHandling = jsonProperty.TypeNameHandling ?? matchingMemberProperty.TypeNameHandling; } return jsonProperty; } protected virtual JsonConverter? ResolveContractConverter(Type objectType) { return JsonTypeReflector.GetJsonConverter(objectType); } private Func GetDefaultCreator(Type createdType) { return JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(createdType); } private void InitializeContract(JsonContract contract) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(contract.NonNullableUnderlyingType); if (cachedAttribute != null) { contract.IsReference = cachedAttribute._isReference; } else { DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(contract.NonNullableUnderlyingType); if (dataContractAttribute != null && dataContractAttribute.IsReference) { contract.IsReference = true; } } contract.Converter = ResolveContractConverter(contract.NonNullableUnderlyingType); contract.InternalConverter = JsonSerializer.GetMatchingConverter(BuiltInConverters, contract.NonNullableUnderlyingType); if (contract.IsInstantiable && (ReflectionUtils.HasDefaultConstructor(contract.CreatedType, nonPublic: true) || contract.CreatedType.IsValueType())) { contract.DefaultCreator = GetDefaultCreator(contract.CreatedType); contract.DefaultCreatorNonPublic = !contract.CreatedType.IsValueType() && ReflectionUtils.GetDefaultConstructor(contract.CreatedType) == null; } ResolveCallbackMethods(contract, contract.NonNullableUnderlyingType); } private void ResolveCallbackMethods(JsonContract contract, Type t) { GetCallbackMethodsForType(t, out List onSerializing, out List onSerialized, out List onDeserializing, out List onDeserialized, out List onError); if (onSerializing != null) { contract.OnSerializingCallbacks.AddRange(onSerializing); } if (onSerialized != null) { contract.OnSerializedCallbacks.AddRange(onSerialized); } if (onDeserializing != null) { contract.OnDeserializingCallbacks.AddRange(onDeserializing); } if (onDeserialized != null) { contract.OnDeserializedCallbacks.AddRange(onDeserialized); } if (onError != null) { contract.OnErrorCallbacks.AddRange(onError); } } private void GetCallbackMethodsForType(Type type, out List? onSerializing, out List? onSerialized, out List? onDeserializing, out List? onDeserialized, out List? onError) { onSerializing = null; onSerialized = null; onDeserializing = null; onDeserialized = null; onError = null; foreach (Type item in GetClassHierarchyForType(type)) { MethodInfo currentCallback = null; MethodInfo currentCallback2 = null; MethodInfo currentCallback3 = null; MethodInfo currentCallback4 = null; MethodInfo currentCallback5 = null; bool flag = ShouldSkipSerializing(item); bool flag2 = ShouldSkipDeserialized(item); MethodInfo[] methods = item.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!methodInfo.ContainsGenericParameters) { Type prevAttributeType = null; ParameterInfo[] parameters = methodInfo.GetParameters(); if (!flag && IsValidCallback(methodInfo, parameters, typeof(OnSerializingAttribute), currentCallback, ref prevAttributeType)) { onSerializing = onSerializing ?? new List(); onSerializing.Add(JsonContract.CreateSerializationCallback(methodInfo)); currentCallback = methodInfo; } if (IsValidCallback(methodInfo, parameters, typeof(OnSerializedAttribute), currentCallback2, ref prevAttributeType)) { onSerialized = onSerialized ?? new List(); onSerialized.Add(JsonContract.CreateSerializationCallback(methodInfo)); currentCallback2 = methodInfo; } if (IsValidCallback(methodInfo, parameters, typeof(OnDeserializingAttribute), currentCallback3, ref prevAttributeType)) { onDeserializing = onDeserializing ?? new List(); onDeserializing.Add(JsonContract.CreateSerializationCallback(methodInfo)); currentCallback3 = methodInfo; } if (!flag2 && IsValidCallback(methodInfo, parameters, typeof(OnDeserializedAttribute), currentCallback4, ref prevAttributeType)) { onDeserialized = onDeserialized ?? new List(); onDeserialized.Add(JsonContract.CreateSerializationCallback(methodInfo)); currentCallback4 = methodInfo; } if (IsValidCallback(methodInfo, parameters, typeof(OnErrorAttribute), currentCallback5, ref prevAttributeType)) { onError = onError ?? new List(); onError.Add(JsonContract.CreateSerializationErrorCallback(methodInfo)); currentCallback5 = methodInfo; } } } } } private static bool IsConcurrentOrObservableCollection(Type t) { if (t.IsGenericType()) { switch (t.GetGenericTypeDefinition().FullName) { case "System.Collections.Concurrent.ConcurrentQueue`1": case "System.Collections.Concurrent.ConcurrentStack`1": case "System.Collections.Concurrent.ConcurrentBag`1": case "System.Collections.Concurrent.ConcurrentDictionary`2": case "System.Collections.ObjectModel.ObservableCollection`1": return true; } } return false; } private static bool ShouldSkipDeserialized(Type t) { if (IsConcurrentOrObservableCollection(t)) { return true; } if (t.Name == "FSharpSet`1" || t.Name == "FSharpMap`2") { return true; } return false; } private static bool ShouldSkipSerializing(Type t) { if (IsConcurrentOrObservableCollection(t)) { return true; } if (t.Name == "FSharpSet`1" || t.Name == "FSharpMap`2") { return true; } return false; } private List GetClassHierarchyForType(Type type) { List list = new List(); Type type2 = type; while (type2 != null && type2 != typeof(object)) { list.Add(type2); type2 = type2.BaseType(); } list.Reverse(); return list; } protected virtual JsonDictionaryContract CreateDictionaryContract(Type objectType) { JsonDictionaryContract jsonDictionaryContract = new JsonDictionaryContract(objectType); InitializeContract(jsonDictionaryContract); JsonContainerAttribute attribute = JsonTypeReflector.GetAttribute(objectType); if (attribute?.NamingStrategyType != null) { NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(attribute); jsonDictionaryContract.DictionaryKeyResolver = (string s) => namingStrategy.GetDictionaryKey(s); } else { jsonDictionaryContract.DictionaryKeyResolver = ResolveDictionaryKey; } ConstructorInfo attributeConstructor = GetAttributeConstructor(jsonDictionaryContract.NonNullableUnderlyingType); if (attributeConstructor != null) { ParameterInfo[] parameters = attributeConstructor.GetParameters(); Type type = ((jsonDictionaryContract.DictionaryKeyType != null && jsonDictionaryContract.DictionaryValueType != null) ? typeof(IEnumerable<>).MakeGenericType(typeof(KeyValuePair<, >).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType)) : typeof(IDictionary)); if (parameters.Length == 0) { jsonDictionaryContract.HasParameterizedCreator = false; } else { if (parameters.Length != 1 || !type.IsAssignableFrom(parameters[0].ParameterType)) { throw new JsonException("Constructor for '{0}' must have no parameters or a single parameter that implements '{1}'.".FormatWith(CultureInfo.InvariantCulture, jsonDictionaryContract.UnderlyingType, type)); } jsonDictionaryContract.HasParameterizedCreator = true; } jsonDictionaryContract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(attributeConstructor); } return jsonDictionaryContract; } protected virtual JsonArrayContract CreateArrayContract(Type objectType) { JsonArrayContract jsonArrayContract = new JsonArrayContract(objectType); InitializeContract(jsonArrayContract); ConstructorInfo attributeConstructor = GetAttributeConstructor(jsonArrayContract.NonNullableUnderlyingType); if (attributeConstructor != null) { ParameterInfo[] parameters = attributeConstructor.GetParameters(); Type type = ((jsonArrayContract.CollectionItemType != null) ? typeof(IEnumerable<>).MakeGenericType(jsonArrayContract.CollectionItemType) : typeof(IEnumerable)); if (parameters.Length == 0) { jsonArrayContract.HasParameterizedCreator = false; } else { if (parameters.Length != 1 || !type.IsAssignableFrom(parameters[0].ParameterType)) { throw new JsonException("Constructor for '{0}' must have no parameters or a single parameter that implements '{1}'.".FormatWith(CultureInfo.InvariantCulture, jsonArrayContract.UnderlyingType, type)); } jsonArrayContract.HasParameterizedCreator = true; } jsonArrayContract.OverrideCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(attributeConstructor); } return jsonArrayContract; } protected virtual JsonPrimitiveContract CreatePrimitiveContract(Type objectType) { JsonPrimitiveContract jsonPrimitiveContract = new JsonPrimitiveContract(objectType); InitializeContract(jsonPrimitiveContract); return jsonPrimitiveContract; } protected virtual JsonLinqContract CreateLinqContract(Type objectType) { JsonLinqContract jsonLinqContract = new JsonLinqContract(objectType); InitializeContract(jsonLinqContract); return jsonLinqContract; } protected virtual JsonISerializableContract CreateISerializableContract(Type objectType) { JsonISerializableContract jsonISerializableContract = new JsonISerializableContract(objectType); InitializeContract(jsonISerializableContract); if (jsonISerializableContract.IsInstantiable) { ConstructorInfo constructor = jsonISerializableContract.NonNullableUnderlyingType.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[2] { typeof(SerializationInfo), typeof(StreamingContext) }, null); if (constructor != null) { ObjectConstructor iSerializableCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); jsonISerializableContract.ISerializableCreator = iSerializableCreator; } } return jsonISerializableContract; } protected virtual JsonDynamicContract CreateDynamicContract(Type objectType) { JsonDynamicContract jsonDynamicContract = new JsonDynamicContract(objectType); InitializeContract(jsonDynamicContract); JsonContainerAttribute attribute = JsonTypeReflector.GetAttribute(objectType); if (attribute?.NamingStrategyType != null) { NamingStrategy namingStrategy = JsonTypeReflector.GetContainerNamingStrategy(attribute); jsonDynamicContract.PropertyNameResolver = (string s) => namingStrategy.GetDictionaryKey(s); } else { jsonDynamicContract.PropertyNameResolver = ResolveDictionaryKey; } jsonDynamicContract.Properties.AddRange(CreateProperties(objectType, MemberSerialization.OptOut)); return jsonDynamicContract; } protected virtual JsonStringContract CreateStringContract(Type objectType) { JsonStringContract jsonStringContract = new JsonStringContract(objectType); InitializeContract(jsonStringContract); return jsonStringContract; } protected virtual JsonContract CreateContract(Type objectType) { Type t = ReflectionUtils.EnsureNotByRefType(objectType); if (IsJsonPrimitiveType(t)) { return CreatePrimitiveContract(objectType); } t = ReflectionUtils.EnsureNotNullableType(t); JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(t); if (cachedAttribute is JsonObjectAttribute) { return CreateObjectContract(objectType); } if (cachedAttribute is JsonArrayAttribute) { return CreateArrayContract(objectType); } if (cachedAttribute is JsonDictionaryAttribute) { return CreateDictionaryContract(objectType); } if (t == typeof(JToken) || t.IsSubclassOf(typeof(JToken))) { return CreateLinqContract(objectType); } if (CollectionUtils.IsDictionaryType(t)) { return CreateDictionaryContract(objectType); } if (typeof(IEnumerable).IsAssignableFrom(t)) { return CreateArrayContract(objectType); } if (CanConvertToString(t)) { return CreateStringContract(objectType); } if (!IgnoreSerializableInterface && typeof(ISerializable).IsAssignableFrom(t) && JsonTypeReflector.IsSerializable(t)) { return CreateISerializableContract(objectType); } if (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(t)) { return CreateDynamicContract(objectType); } if (IsIConvertible(t)) { return CreatePrimitiveContract(t); } return CreateObjectContract(objectType); } internal static bool IsJsonPrimitiveType(Type t) { PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(t); if (typeCode != 0) { return typeCode != PrimitiveTypeCode.Object; } return false; } internal static bool IsIConvertible(Type t) { if (typeof(IConvertible).IsAssignableFrom(t) || (ReflectionUtils.IsNullableType(t) && typeof(IConvertible).IsAssignableFrom(Nullable.GetUnderlyingType(t)))) { return !typeof(JToken).IsAssignableFrom(t); } return false; } internal static bool CanConvertToString(Type type) { if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out TypeConverter _)) { return true; } if (type == typeof(Type) || type.IsSubclassOf(typeof(Type))) { return true; } return false; } private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo? currentCallback, ref Type? prevAttributeType) { if (!method.IsDefined(attributeType, inherit: false)) { return false; } if (currentCallback != null) { throw new JsonException("Invalid attribute. Both '{0}' and '{1}' in type '{2}' have '{3}'.".FormatWith(CultureInfo.InvariantCulture, method, currentCallback, GetClrTypeFullName(method.DeclaringType), attributeType)); } if (prevAttributeType != null) { throw new JsonException("Invalid Callback. Method '{3}' in type '{2}' has both '{0}' and '{1}'.".FormatWith(CultureInfo.InvariantCulture, prevAttributeType, attributeType, GetClrTypeFullName(method.DeclaringType), method)); } if (method.IsVirtual) { throw new JsonException("Virtual Method '{0}' of type '{1}' cannot be marked with '{2}' attribute.".FormatWith(CultureInfo.InvariantCulture, method, GetClrTypeFullName(method.DeclaringType), attributeType)); } if (method.ReturnType != typeof(void)) { throw new JsonException("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method)); } if (attributeType == typeof(OnErrorAttribute)) { if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext)) { throw new JsonException("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext), typeof(ErrorContext))); } } else if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext)) { throw new JsonException("Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext))); } prevAttributeType = attributeType; return true; } internal static string GetClrTypeFullName(Type type) { if (type.IsGenericTypeDefinition() || !type.ContainsGenericParameters()) { return type.FullName; } return "{0}.{1}".FormatWith(CultureInfo.InvariantCulture, type.Namespace, type.Name); } protected virtual IList CreateProperties(Type type, MemberSerialization memberSerialization) { List obj = GetSerializableMembers(type) ?? throw new JsonSerializationException("Null collection of serializable members returned."); DefaultJsonNameTable nameTable = GetNameTable(); JsonPropertyCollection jsonPropertyCollection = new JsonPropertyCollection(type); foreach (MemberInfo item in obj) { JsonProperty jsonProperty = CreateProperty(item, memberSerialization); if (jsonProperty != null) { lock (nameTable) { jsonProperty.PropertyName = nameTable.Add(jsonProperty.PropertyName); } jsonPropertyCollection.AddProperty(jsonProperty); } } return jsonPropertyCollection.OrderBy((JsonProperty p) => p.Order ?? (-1)).ToList(); } internal virtual DefaultJsonNameTable GetNameTable() { return _nameTable; } protected virtual IValueProvider CreateMemberValueProvider(MemberInfo member) { if (DynamicCodeGeneration) { return new DynamicValueProvider(member); } return new ReflectionValueProvider(member); } protected virtual JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty jsonProperty = new JsonProperty(); jsonProperty.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member); jsonProperty.DeclaringType = member.DeclaringType; jsonProperty.ValueProvider = CreateMemberValueProvider(member); jsonProperty.AttributeProvider = new ReflectionAttributeProvider(member); SetPropertySettingsFromAttributes(jsonProperty, member, member.Name, member.DeclaringType, memberSerialization, out var allowNonPublicAccess); if (memberSerialization != MemberSerialization.Fields) { jsonProperty.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess); jsonProperty.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess, jsonProperty.HasMemberAttribute); } else { jsonProperty.Readable = true; jsonProperty.Writable = true; } if (!IgnoreShouldSerializeMembers) { jsonProperty.ShouldSerialize = CreateShouldSerializeTest(member); } if (!IgnoreIsSpecifiedMembers) { SetIsSpecifiedActions(jsonProperty, member, allowNonPublicAccess); } return jsonProperty; } private void SetPropertySettingsFromAttributes(JsonProperty property, object attributeProvider, string name, Type declaringType, MemberSerialization memberSerialization, out bool allowNonPublicAccess) { DataContractAttribute? dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(declaringType); MemberInfo memberInfo = attributeProvider as MemberInfo; DataMemberAttribute dataMemberAttribute = ((dataContractAttribute == null || !(memberInfo != null)) ? null : JsonTypeReflector.GetDataMemberAttribute(memberInfo)); JsonPropertyAttribute attribute = JsonTypeReflector.GetAttribute(attributeProvider); JsonRequiredAttribute? attribute2 = JsonTypeReflector.GetAttribute(attributeProvider); string text; bool hasSpecifiedName; if (attribute != null && attribute.PropertyName != null) { text = attribute.PropertyName; hasSpecifiedName = true; } else if (dataMemberAttribute != null && dataMemberAttribute.Name != null) { text = dataMemberAttribute.Name; hasSpecifiedName = true; } else { text = name; hasSpecifiedName = false; } JsonContainerAttribute attribute3 = JsonTypeReflector.GetAttribute(declaringType); NamingStrategy namingStrategy = ((attribute?.NamingStrategyType != null) ? JsonTypeReflector.CreateNamingStrategyInstance(attribute.NamingStrategyType, attribute.NamingStrategyParameters) : ((!(attribute3?.NamingStrategyType != null)) ? NamingStrategy : JsonTypeReflector.GetContainerNamingStrategy(attribute3))); if (namingStrategy != null) { property.PropertyName = namingStrategy.GetPropertyName(text, hasSpecifiedName); } else { property.PropertyName = ResolvePropertyName(text); } property.UnderlyingName = name; bool flag = false; if (attribute != null) { property._required = attribute._required; property.Order = attribute._order; property.DefaultValueHandling = attribute._defaultValueHandling; flag = true; property.NullValueHandling = attribute._nullValueHandling; property.ReferenceLoopHandling = attribute._referenceLoopHandling; property.ObjectCreationHandling = attribute._objectCreationHandling; property.TypeNameHandling = attribute._typeNameHandling; property.IsReference = attribute._isReference; property.ItemIsReference = attribute._itemIsReference; property.ItemConverter = ((attribute.ItemConverterType != null) ? JsonTypeReflector.CreateJsonConverterInstance(attribute.ItemConverterType, attribute.ItemConverterParameters) : null); property.ItemReferenceLoopHandling = attribute._itemReferenceLoopHandling; property.ItemTypeNameHandling = attribute._itemTypeNameHandling; } else { property.NullValueHandling = null; property.ReferenceLoopHandling = null; property.ObjectCreationHandling = null; property.TypeNameHandling = null; property.IsReference = null; property.ItemIsReference = null; property.ItemConverter = null; property.ItemReferenceLoopHandling = null; property.ItemTypeNameHandling = null; if (dataMemberAttribute != null) { property._required = (dataMemberAttribute.IsRequired ? Required.AllowNull : Required.Default); property.Order = ((dataMemberAttribute.Order != -1) ? new int?(dataMemberAttribute.Order) : null); property.DefaultValueHandling = ((!dataMemberAttribute.EmitDefaultValue) ? new DefaultValueHandling?(DefaultValueHandling.Ignore) : null); flag = true; } } if (attribute2 != null) { property._required = Required.Always; flag = true; } property.HasMemberAttribute = flag; bool flag2 = JsonTypeReflector.GetAttribute(attributeProvider) != null || JsonTypeReflector.GetAttribute(attributeProvider) != null || JsonTypeReflector.IsNonSerializable(attributeProvider); if (memberSerialization != MemberSerialization.OptIn) { bool flag3 = false; flag3 = JsonTypeReflector.GetAttribute(attributeProvider) != null; property.Ignored = flag2 || flag3; } else { property.Ignored = flag2 || !flag; } property.Converter = JsonTypeReflector.GetJsonConverter(attributeProvider); DefaultValueAttribute attribute4 = JsonTypeReflector.GetAttribute(attributeProvider); if (attribute4 != null) { property.DefaultValue = attribute4.Value; } allowNonPublicAccess = false; if ((DefaultMembersSearchFlags & BindingFlags.NonPublic) == BindingFlags.NonPublic) { allowNonPublicAccess = true; } if (flag) { allowNonPublicAccess = true; } if (memberSerialization == MemberSerialization.Fields) { allowNonPublicAccess = true; } } private Predicate? CreateShouldSerializeTest(MemberInfo member) { MethodInfo method = member.DeclaringType.GetMethod("ShouldSerialize" + member.Name, ReflectionUtils.EmptyTypes); if (method == null || method.ReturnType != typeof(bool)) { return null; } MethodCall shouldSerializeCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall(method); return (object o) => (bool)shouldSerializeCall(o); } private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member, bool allowNonPublicAccess) { MemberInfo memberInfo = member.DeclaringType.GetProperty(member.Name + "Specified", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (memberInfo == null) { memberInfo = member.DeclaringType.GetField(member.Name + "Specified", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } if (!(memberInfo == null) && !(ReflectionUtils.GetMemberUnderlyingType(memberInfo) != typeof(bool))) { Func specifiedPropertyGet = JsonTypeReflector.ReflectionDelegateFactory.CreateGet(memberInfo); property.GetIsSpecified = (object o) => (bool)specifiedPropertyGet(o); if (ReflectionUtils.CanSetMemberValue(memberInfo, allowNonPublicAccess, canSetReadOnly: false)) { property.SetIsSpecified = JsonTypeReflector.ReflectionDelegateFactory.CreateSet(memberInfo); } } } protected virtual string ResolvePropertyName(string propertyName) { if (NamingStrategy != null) { return NamingStrategy.GetPropertyName(propertyName, hasSpecifiedName: false); } return propertyName; } protected virtual string ResolveExtensionDataName(string extensionDataName) { if (NamingStrategy != null) { return NamingStrategy.GetExtensionDataName(extensionDataName); } return extensionDataName; } protected virtual string ResolveDictionaryKey(string dictionaryKey) { if (NamingStrategy != null) { return NamingStrategy.GetDictionaryKey(dictionaryKey); } return ResolvePropertyName(dictionaryKey); } public string GetResolvedPropertyName(string propertyName) { return ResolvePropertyName(propertyName); } } internal class DefaultNamingStrategy : NamingStrategy { protected override string ResolvePropertyName(string name) { return name; } } internal class DefaultReferenceResolver : IReferenceResolver { private int _referenceCount; private BidirectionalDictionary GetMappings(object context) { JsonSerializerInternalBase jsonSerializerInternalBase = context as JsonSerializerInternalBase; if (jsonSerializerInternalBase == null) { if (!(context is JsonSerializerProxy jsonSerializerProxy)) { throw new JsonException("The DefaultReferenceResolver can only be used internally."); } jsonSerializerInternalBase = jsonSerializerProxy.GetInternalSerializer(); } return jsonSerializerInternalBase.DefaultReferenceMappings; } public object ResolveReference(object context, string reference) { GetMappings(context).TryGetByFirst(reference, out object second); return second; } public string GetReference(object context, object value) { BidirectionalDictionary mappings = GetMappings(context); if (!mappings.TryGetBySecond(value, out string first)) { _referenceCount++; first = _referenceCount.ToString(CultureInfo.InvariantCulture); mappings.Set(first, value); } return first; } public void AddReference(object context, string reference, object value) { GetMappings(context).Set(reference, value); } public bool IsReferenced(object context, object value) { string first; return GetMappings(context).TryGetBySecond(value, out first); } } internal class DefaultSerializationBinder : SerializationBinder, ISerializationBinder { internal static readonly DefaultSerializationBinder Instance = new DefaultSerializationBinder(); private readonly ThreadSafeStore, Type> _typeCache; public DefaultSerializationBinder() { _typeCache = new ThreadSafeStore, Type>(GetTypeFromTypeNameKey); } private Type GetTypeFromTypeNameKey(StructMultiKey typeNameKey) { string value = typeNameKey.Value1; string value2 = typeNameKey.Value2; if (value != null) { Assembly assembly = Assembly.LoadWithPartialName(value); if (assembly == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly2 in assemblies) { if (assembly2.FullName == value || assembly2.GetName().Name == value) { assembly = assembly2; break; } } } if (assembly == null) { throw new JsonSerializationException("Could not load assembly '{0}'.".FormatWith(CultureInfo.InvariantCulture, value)); } Type type = assembly.GetType(value2); if (type == null) { if (StringUtils.IndexOf(value2, '`') >= 0) { try { type = GetGenericTypeFromTypeName(value2, assembly); } catch (Exception innerException) { throw new JsonSerializationException("Could not find type '{0}' in assembly '{1}'.".FormatWith(CultureInfo.InvariantCulture, value2, assembly.FullName), innerException); } } if (type == null) { throw new JsonSerializationException("Could not find type '{0}' in assembly '{1}'.".FormatWith(CultureInfo.InvariantCulture, value2, assembly.FullName)); } } return type; } return Type.GetType(value2); } private Type? GetGenericTypeFromTypeName(string typeName, Assembly assembly) { Type result = null; int num = StringUtils.IndexOf(typeName, '['); if (num >= 0) { string name = typeName.Substring(0, num); Type type = assembly.GetType(name); if (type != null) { List list = new List(); int num2 = 0; int num3 = 0; int num4 = typeName.Length - 1; for (int i = num + 1; i < num4; i++) { switch (typeName[i]) { case '[': if (num2 == 0) { num3 = i + 1; } num2++; break; case ']': num2--; if (num2 == 0) { StructMultiKey typeNameKey = ReflectionUtils.SplitFullyQualifiedTypeName(typeName.Substring(num3, i - num3)); list.Add(GetTypeByName(typeNameKey)); } break; } } result = type.MakeGenericType(list.ToArray()); } } return result; } private Type GetTypeByName(StructMultiKey typeNameKey) { return _typeCache.Get(typeNameKey); } public override Type BindToType(string? assemblyName, string typeName) { return GetTypeByName(new StructMultiKey(assemblyName, typeName)); } public override void BindToName(Type serializedType, out string? assemblyName, out string? typeName) { assemblyName = serializedType.Assembly.FullName; typeName = serializedType.FullName; } } internal class DiagnosticsTraceWriter : ITraceWriter { public TraceLevel LevelFilter { get; set; } private TraceEventType GetTraceEventType(TraceLevel level) { return level switch { TraceLevel.Error => TraceEventType.Error, TraceLevel.Warning => TraceEventType.Warning, TraceLevel.Info => TraceEventType.Information, TraceLevel.Verbose => TraceEventType.Verbose, _ => throw new ArgumentOutOfRangeException("level"), }; } public void Trace(TraceLevel level, string message, Exception? ex) { if (level == TraceLevel.Off) { return; } TraceEventCache eventCache = new TraceEventCache(); TraceEventType traceEventType = GetTraceEventType(level); foreach (TraceListener listener in System.Diagnostics.Trace.Listeners) { if (!listener.IsThreadSafe) { lock (listener) { listener.TraceEvent(eventCache, "Newtonsoft.Json", traceEventType, 0, message); } } else { listener.TraceEvent(eventCache, "Newtonsoft.Json", traceEventType, 0, message); } if (System.Diagnostics.Trace.AutoFlush) { listener.Flush(); } } } } internal class DynamicValueProvider : IValueProvider { private readonly MemberInfo _memberInfo; private Func? _getter; private Action? _setter; public DynamicValueProvider(MemberInfo memberInfo) { ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo"); _memberInfo = memberInfo; } public void SetValue(object target, object? value) { try { if (_setter == null) { _setter = DynamicReflectionDelegateFactory.Instance.CreateSet(_memberInfo); } _setter(target, value); } catch (Exception innerException) { throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } public object? GetValue(object target) { try { if (_getter == null) { _getter = DynamicReflectionDelegateFactory.Instance.CreateGet(_memberInfo); } return _getter(target); } catch (Exception innerException) { throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } } internal class ErrorContext { internal bool Traced { get; set; } public Exception Error { get; } public object? OriginalObject { get; } public object? Member { get; } public string Path { get; } public bool Handled { get; set; } internal ErrorContext(object? originalObject, object? member, string path, Exception error) { OriginalObject = originalObject; Member = member; Error = error; Path = path; } } internal class ErrorEventArgs : EventArgs { public object? CurrentObject { get; } public ErrorContext ErrorContext { get; } public ErrorEventArgs(object? currentObject, ErrorContext errorContext) { CurrentObject = currentObject; ErrorContext = errorContext; } } internal class ExpressionValueProvider : IValueProvider { private readonly MemberInfo _memberInfo; private Func? _getter; private Action? _setter; public ExpressionValueProvider(MemberInfo memberInfo) { ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo"); _memberInfo = memberInfo; } public void SetValue(object target, object? value) { try { if (_setter == null) { _setter = ExpressionReflectionDelegateFactory.Instance.CreateSet(_memberInfo); } _setter(target, value); } catch (Exception innerException) { throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } public object? GetValue(object target) { try { if (_getter == null) { _getter = ExpressionReflectionDelegateFactory.Instance.CreateGet(_memberInfo); } return _getter(target); } catch (Exception innerException) { throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } } internal interface IAttributeProvider { IList GetAttributes(bool inherit); IList GetAttributes(Type attributeType, bool inherit); } internal interface IContractResolver { JsonContract ResolveContract(Type type); } internal interface IReferenceResolver { object ResolveReference(object context, string reference); string GetReference(object context, object value); bool IsReferenced(object context, object value); void AddReference(object context, string reference, object value); } internal interface ISerializationBinder { Type BindToType(string? assemblyName, string typeName); void BindToName(Type serializedType, out string? assemblyName, out string? typeName); } internal interface ITraceWriter { TraceLevel LevelFilter { get; } void Trace(TraceLevel level, string message, Exception? ex); } internal interface IValueProvider { void SetValue(object target, object? value); object? GetValue(object target); } internal class JsonArrayContract : JsonContainerContract { private readonly Type? _genericCollectionDefinitionType; private Type? _genericWrapperType; private ObjectConstructor? _genericWrapperCreator; private Func? _genericTemporaryCollectionCreator; private readonly ConstructorInfo? _parameterizedConstructor; private ObjectConstructor? _parameterizedCreator; private ObjectConstructor? _overrideCreator; public Type? CollectionItemType { get; } public bool IsMultidimensionalArray { get; } internal bool IsArray { get; } internal bool ShouldCreateWrapper { get; } internal bool CanDeserialize { get; private set; } internal ObjectConstructor? ParameterizedCreator { get { if (_parameterizedCreator == null && _parameterizedConstructor != null) { _parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(_parameterizedConstructor); } return _parameterizedCreator; } } public ObjectConstructor? OverrideCreator { get { return _overrideCreator; } set { _overrideCreator = value; CanDeserialize = true; } } public bool HasParameterizedCreator { get; set; } internal bool HasParameterizedCreatorInternal { get { if (!HasParameterizedCreator && _parameterizedCreator == null) { return _parameterizedConstructor != null; } return true; } } public JsonArrayContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Array; IsArray = base.CreatedType.IsArray || (NonNullableUnderlyingType.IsGenericType() && NonNullableUnderlyingType.GetGenericTypeDefinition().FullName == "System.Linq.EmptyPartition`1"); bool canDeserialize; Type implementingType; if (IsArray) { CollectionItemType = ReflectionUtils.GetCollectionItemType(base.UnderlyingType); IsReadOnlyOrFixedSize = true; _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); canDeserialize = true; IsMultidimensionalArray = base.CreatedType.IsArray && base.UnderlyingType.GetArrayRank() > 1; } else if (typeof(IList).IsAssignableFrom(NonNullableUnderlyingType)) { if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType)) { CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0]; } else { CollectionItemType = ReflectionUtils.GetCollectionItemType(NonNullableUnderlyingType); } if (NonNullableUnderlyingType == typeof(IList)) { base.CreatedType = typeof(List); } if (CollectionItemType != null) { _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType); } IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(NonNullableUnderlyingType, typeof(ReadOnlyCollection<>)); canDeserialize = true; } else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType)) { CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0]; if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(ICollection<>)) || ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IList<>))) { base.CreatedType = typeof(List<>).MakeGenericType(CollectionItemType); } if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(ISet<>))) { base.CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType); } _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType); canDeserialize = true; ShouldCreateWrapper = true; } else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyCollection<>), out implementingType)) { CollectionItemType = implementingType.GetGenericArguments()[0]; if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyCollection<>)) || ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyList<>))) { base.CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType); } _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(base.CreatedType, CollectionItemType); StoreFSharpListCreatorIfNecessary(NonNullableUnderlyingType); IsReadOnlyOrFixedSize = true; canDeserialize = HasParameterizedCreatorInternal; } else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IEnumerable<>), out implementingType)) { CollectionItemType = implementingType.GetGenericArguments()[0]; if (ReflectionUtils.IsGenericDefinition(base.UnderlyingType, typeof(IEnumerable<>))) { base.CreatedType = typeof(List<>).MakeGenericType(CollectionItemType); } _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(NonNullableUnderlyingType, CollectionItemType); StoreFSharpListCreatorIfNecessary(NonNullableUnderlyingType); if (NonNullableUnderlyingType.IsGenericType() && NonNullableUnderlyingType.GetGenericTypeDefinition() == typeof(IEnumerable<>)) { _genericCollectionDefinitionType = implementingType; IsReadOnlyOrFixedSize = false; ShouldCreateWrapper = false; canDeserialize = true; } else { _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType); IsReadOnlyOrFixedSize = true; ShouldCreateWrapper = true; canDeserialize = HasParameterizedCreatorInternal; } } else { canDeserialize = false; ShouldCreateWrapper = true; } CanDeserialize = canDeserialize; if (CollectionItemType != null && ImmutableCollectionsUtils.TryBuildImmutableForArrayContract(NonNullableUnderlyingType, CollectionItemType, out Type createdType, out ObjectConstructor parameterizedCreator)) { base.CreatedType = createdType; _parameterizedCreator = parameterizedCreator; IsReadOnlyOrFixedSize = true; CanDeserialize = true; } } internal IWrappedCollection CreateWrapper(object list) { if (_genericWrapperCreator == null) { _genericWrapperType = typeof(CollectionWrapper<>).MakeGenericType(CollectionItemType); Type type = ((!ReflectionUtils.InheritsGenericDefinition(_genericCollectionDefinitionType, typeof(List<>)) && !(_genericCollectionDefinitionType.GetGenericTypeDefinition() == typeof(IEnumerable<>))) ? _genericCollectionDefinitionType : typeof(ICollection<>).MakeGenericType(CollectionItemType)); ConstructorInfo constructor = _genericWrapperType.GetConstructor(new Type[1] { type }); _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); } return (IWrappedCollection)_genericWrapperCreator(list); } internal IList CreateTemporaryCollection() { if (_genericTemporaryCollectionCreator == null) { Type type = ((IsMultidimensionalArray || CollectionItemType == null) ? typeof(object) : CollectionItemType); Type type2 = typeof(List<>).MakeGenericType(type); _genericTemporaryCollectionCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(type2); } return (IList)_genericTemporaryCollectionCreator(); } private void StoreFSharpListCreatorIfNecessary(Type underlyingType) { if (!HasParameterizedCreatorInternal && underlyingType.Name == "FSharpList`1") { FSharpUtils.EnsureInitialized(underlyingType.Assembly()); _parameterizedCreator = FSharpUtils.Instance.CreateSeq(CollectionItemType); } } } internal class JsonContainerContract : JsonContract { private JsonContract? _itemContract; private JsonContract? _finalItemContract; internal JsonContract? ItemContract { get { return _itemContract; } set { _itemContract = value; if (_itemContract != null) { _finalItemContract = (_itemContract.UnderlyingType.IsSealed() ? _itemContract : null); } else { _finalItemContract = null; } } } internal JsonContract? FinalItemContract => _finalItemContract; public JsonConverter? ItemConverter { get; set; } public bool? ItemIsReference { get; set; } public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; } public TypeNameHandling? ItemTypeNameHandling { get; set; } internal JsonContainerContract(Type underlyingType) : base(underlyingType) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(underlyingType); if (cachedAttribute != null) { if (cachedAttribute.ItemConverterType != null) { ItemConverter = JsonTypeReflector.CreateJsonConverterInstance(cachedAttribute.ItemConverterType, cachedAttribute.ItemConverterParameters); } ItemIsReference = cachedAttribute._itemIsReference; ItemReferenceLoopHandling = cachedAttribute._itemReferenceLoopHandling; ItemTypeNameHandling = cachedAttribute._itemTypeNameHandling; } } } internal enum JsonContractType { None, Object, Array, Primitive, String, Dictionary, Dynamic, Serializable, Linq } internal delegate void SerializationCallback(object o, StreamingContext context); internal delegate void SerializationErrorCallback(object o, StreamingContext context, ErrorContext errorContext); internal delegate void ExtensionDataSetter(object o, string key, object? value); internal delegate IEnumerable>? ExtensionDataGetter(object o); internal abstract class JsonContract { internal bool IsNullable; internal bool IsConvertable; internal bool IsEnum; internal Type NonNullableUnderlyingType; internal ReadType InternalReadType; internal JsonContractType ContractType; internal bool IsReadOnlyOrFixedSize; internal bool IsSealed; internal bool IsInstantiable; private List? _onDeserializedCallbacks; private List? _onDeserializingCallbacks; private List? _onSerializedCallbacks; private List? _onSerializingCallbacks; private List? _onErrorCallbacks; private Type _createdType; public Type UnderlyingType { get; } public Type CreatedType { get { return _createdType; } set { ValidationUtils.ArgumentNotNull(value, "value"); _createdType = value; IsSealed = _createdType.IsSealed(); IsInstantiable = !_createdType.IsInterface() && !_createdType.IsAbstract(); } } public bool? IsReference { get; set; } public JsonConverter? Converter { get; set; } public JsonConverter? InternalConverter { get; internal set; } public IList OnDeserializedCallbacks { get { if (_onDeserializedCallbacks == null) { _onDeserializedCallbacks = new List(); } return _onDeserializedCallbacks; } } public IList OnDeserializingCallbacks { get { if (_onDeserializingCallbacks == null) { _onDeserializingCallbacks = new List(); } return _onDeserializingCallbacks; } } public IList OnSerializedCallbacks { get { if (_onSerializedCallbacks == null) { _onSerializedCallbacks = new List(); } return _onSerializedCallbacks; } } public IList OnSerializingCallbacks { get { if (_onSerializingCallbacks == null) { _onSerializingCallbacks = new List(); } return _onSerializingCallbacks; } } public IList OnErrorCallbacks { get { if (_onErrorCallbacks == null) { _onErrorCallbacks = new List(); } return _onErrorCallbacks; } } public Func? DefaultCreator { get; set; } public bool DefaultCreatorNonPublic { get; set; } internal JsonContract(Type underlyingType) { ValidationUtils.ArgumentNotNull(underlyingType, "underlyingType"); UnderlyingType = underlyingType; underlyingType = ReflectionUtils.EnsureNotByRefType(underlyingType); IsNullable = ReflectionUtils.IsNullable(underlyingType); NonNullableUnderlyingType = ((IsNullable && ReflectionUtils.IsNullableType(underlyingType)) ? Nullable.GetUnderlyingType(underlyingType) : underlyingType); _createdType = (CreatedType = NonNullableUnderlyingType); IsConvertable = ConvertUtils.IsConvertible(NonNullableUnderlyingType); IsEnum = NonNullableUnderlyingType.IsEnum(); InternalReadType = ReadType.Read; } internal void InvokeOnSerializing(object o, StreamingContext context) { if (_onSerializingCallbacks == null) { return; } foreach (SerializationCallback onSerializingCallback in _onSerializingCallbacks) { onSerializingCallback(o, context); } } internal void InvokeOnSerialized(object o, StreamingContext context) { if (_onSerializedCallbacks == null) { return; } foreach (SerializationCallback onSerializedCallback in _onSerializedCallbacks) { onSerializedCallback(o, context); } } internal void InvokeOnDeserializing(object o, StreamingContext context) { if (_onDeserializingCallbacks == null) { return; } foreach (SerializationCallback onDeserializingCallback in _onDeserializingCallbacks) { onDeserializingCallback(o, context); } } internal void InvokeOnDeserialized(object o, StreamingContext context) { if (_onDeserializedCallbacks == null) { return; } foreach (SerializationCallback onDeserializedCallback in _onDeserializedCallbacks) { onDeserializedCallback(o, context); } } internal void InvokeOnError(object o, StreamingContext context, ErrorContext errorContext) { if (_onErrorCallbacks == null) { return; } foreach (SerializationErrorCallback onErrorCallback in _onErrorCallbacks) { onErrorCallback(o, context, errorContext); } } internal static SerializationCallback CreateSerializationCallback(MethodInfo callbackMethodInfo) { MethodInfo callbackMethodInfo2 = callbackMethodInfo; return delegate(object o, StreamingContext context) { callbackMethodInfo2.Invoke(o, new object[1] { context }); }; } internal static SerializationErrorCallback CreateSerializationErrorCallback(MethodInfo callbackMethodInfo) { MethodInfo callbackMethodInfo2 = callbackMethodInfo; return delegate(object o, StreamingContext context, ErrorContext econtext) { callbackMethodInfo2.Invoke(o, new object[2] { context, econtext }); }; } } internal class JsonDictionaryContract : JsonContainerContract { private readonly Type? _genericCollectionDefinitionType; private Type? _genericWrapperType; private ObjectConstructor? _genericWrapperCreator; private Func? _genericTemporaryDictionaryCreator; private readonly ConstructorInfo? _parameterizedConstructor; private ObjectConstructor? _overrideCreator; private ObjectConstructor? _parameterizedCreator; public Func? DictionaryKeyResolver { get; set; } public Type? DictionaryKeyType { get; } public Type? DictionaryValueType { get; } internal JsonContract? KeyContract { get; set; } internal bool ShouldCreateWrapper { get; } internal ObjectConstructor? ParameterizedCreator { get { if (_parameterizedCreator == null && _parameterizedConstructor != null) { _parameterizedCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(_parameterizedConstructor); } return _parameterizedCreator; } } public ObjectConstructor? OverrideCreator { get { return _overrideCreator; } set { _overrideCreator = value; } } public bool HasParameterizedCreator { get; set; } internal bool HasParameterizedCreatorInternal { get { if (!HasParameterizedCreator && _parameterizedCreator == null) { return _parameterizedConstructor != null; } return true; } } public JsonDictionaryContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Dictionary; Type keyType; Type valueType; if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IDictionary<, >), out _genericCollectionDefinitionType)) { keyType = _genericCollectionDefinitionType.GetGenericArguments()[0]; valueType = _genericCollectionDefinitionType.GetGenericArguments()[1]; if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IDictionary<, >))) { base.CreatedType = typeof(Dictionary<, >).MakeGenericType(keyType, valueType); } else if (NonNullableUnderlyingType.IsGenericType() && NonNullableUnderlyingType.GetGenericTypeDefinition().FullName == "System.Collections.Concurrent.ConcurrentDictionary`2") { ShouldCreateWrapper = true; } IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(NonNullableUnderlyingType, typeof(ReadOnlyDictionary<, >)); } else if (ReflectionUtils.ImplementsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyDictionary<, >), out _genericCollectionDefinitionType)) { keyType = _genericCollectionDefinitionType.GetGenericArguments()[0]; valueType = _genericCollectionDefinitionType.GetGenericArguments()[1]; if (ReflectionUtils.IsGenericDefinition(NonNullableUnderlyingType, typeof(IReadOnlyDictionary<, >))) { base.CreatedType = typeof(ReadOnlyDictionary<, >).MakeGenericType(keyType, valueType); } IsReadOnlyOrFixedSize = true; } else { ReflectionUtils.GetDictionaryKeyValueTypes(NonNullableUnderlyingType, out keyType, out valueType); if (NonNullableUnderlyingType == typeof(IDictionary)) { base.CreatedType = typeof(Dictionary); } } if (keyType != null && valueType != null) { _parameterizedConstructor = CollectionUtils.ResolveEnumerableCollectionConstructor(base.CreatedType, typeof(KeyValuePair<, >).MakeGenericType(keyType, valueType), typeof(IDictionary<, >).MakeGenericType(keyType, valueType)); if (!HasParameterizedCreatorInternal && NonNullableUnderlyingType.Name == "FSharpMap`2") { FSharpUtils.EnsureInitialized(NonNullableUnderlyingType.Assembly()); _parameterizedCreator = FSharpUtils.Instance.CreateMap(keyType, valueType); } } if (!typeof(IDictionary).IsAssignableFrom(base.CreatedType)) { ShouldCreateWrapper = true; } DictionaryKeyType = keyType; DictionaryValueType = valueType; if (DictionaryKeyType != null && DictionaryValueType != null && ImmutableCollectionsUtils.TryBuildImmutableForDictionaryContract(NonNullableUnderlyingType, DictionaryKeyType, DictionaryValueType, out Type createdType, out ObjectConstructor parameterizedCreator)) { base.CreatedType = createdType; _parameterizedCreator = parameterizedCreator; IsReadOnlyOrFixedSize = true; } } internal IWrappedDictionary CreateWrapper(object dictionary) { if (_genericWrapperCreator == null) { _genericWrapperType = typeof(DictionaryWrapper<, >).MakeGenericType(DictionaryKeyType, DictionaryValueType); ConstructorInfo constructor = _genericWrapperType.GetConstructor(new Type[1] { _genericCollectionDefinitionType }); _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructor); } return (IWrappedDictionary)_genericWrapperCreator(dictionary); } internal IDictionary CreateTemporaryDictionary() { if (_genericTemporaryDictionaryCreator == null) { Type type = typeof(Dictionary<, >).MakeGenericType(DictionaryKeyType ?? typeof(object), DictionaryValueType ?? typeof(object)); _genericTemporaryDictionaryCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor(type); } return (IDictionary)_genericTemporaryDictionaryCreator(); } } internal class JsonDynamicContract : JsonContainerContract { private readonly ThreadSafeStore>> _callSiteGetters = new ThreadSafeStore>>(CreateCallSiteGetter); private readonly ThreadSafeStore>> _callSiteSetters = new ThreadSafeStore>>(CreateCallSiteSetter); public JsonPropertyCollection Properties { get; } public Func? PropertyNameResolver { get; set; } private static CallSite> CreateCallSiteGetter(string name) { return CallSite>.Create(new NoThrowGetBinderMember((GetMemberBinder)DynamicUtils.BinderWrapper.GetMember(name, typeof(DynamicUtils)))); } private static CallSite> CreateCallSiteSetter(string name) { return CallSite>.Create(new NoThrowSetBinderMember((SetMemberBinder)DynamicUtils.BinderWrapper.SetMember(name, typeof(DynamicUtils)))); } public JsonDynamicContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Dynamic; Properties = new JsonPropertyCollection(base.UnderlyingType); } internal bool TryGetMember(IDynamicMetaObjectProvider dynamicProvider, string name, out object? value) { ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider"); CallSite> callSite = _callSiteGetters.Get(name); object obj = callSite.Target(callSite, dynamicProvider); if (obj != NoThrowExpressionVisitor.ErrorResult) { value = obj; return true; } value = null; return false; } internal bool TrySetMember(IDynamicMetaObjectProvider dynamicProvider, string name, object? value) { ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider"); CallSite> callSite = _callSiteSetters.Get(name); return callSite.Target(callSite, dynamicProvider, value) != NoThrowExpressionVisitor.ErrorResult; } } internal class JsonFormatterConverter : IFormatterConverter { private readonly JsonSerializerInternalReader _reader; private readonly JsonISerializableContract _contract; private readonly JsonProperty? _member; public JsonFormatterConverter(JsonSerializerInternalReader reader, JsonISerializableContract contract, JsonProperty? member) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(contract, "contract"); _reader = reader; _contract = contract; _member = member; } private T GetTokenValue(object value) { ValidationUtils.ArgumentNotNull(value, "value"); return (T)System.Convert.ChangeType(((JValue)value).Value, typeof(T), CultureInfo.InvariantCulture); } public object Convert(object value, Type type) { ValidationUtils.ArgumentNotNull(value, "value"); if (!(value is JToken token)) { throw new ArgumentException("Value is not a JToken.", "value"); } return _reader.CreateISerializableItem(token, type, _contract, _member); } public object Convert(object value, TypeCode typeCode) { ValidationUtils.ArgumentNotNull(value, "value"); return System.Convert.ChangeType((value is JValue jValue) ? jValue.Value : value, typeCode, CultureInfo.InvariantCulture); } public bool ToBoolean(object value) { return GetTokenValue(value); } public byte ToByte(object value) { return GetTokenValue(value); } public char ToChar(object value) { return GetTokenValue(value); } public DateTime ToDateTime(object value) { return GetTokenValue(value); } public decimal ToDecimal(object value) { return GetTokenValue(value); } public double ToDouble(object value) { return GetTokenValue(value); } public short ToInt16(object value) { return GetTokenValue(value); } public int ToInt32(object value) { return GetTokenValue(value); } public long ToInt64(object value) { return GetTokenValue(value); } public sbyte ToSByte(object value) { return GetTokenValue(value); } public float ToSingle(object value) { return GetTokenValue(value); } public string ToString(object value) { return GetTokenValue(value); } public ushort ToUInt16(object value) { return GetTokenValue(value); } public uint ToUInt32(object value) { return GetTokenValue(value); } public ulong ToUInt64(object value) { return GetTokenValue(value); } } internal class JsonISerializableContract : JsonContainerContract { public ObjectConstructor? ISerializableCreator { get; set; } public JsonISerializableContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Serializable; } } internal class JsonLinqContract : JsonContract { public JsonLinqContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Linq; } } internal class JsonObjectContract : JsonContainerContract { internal bool ExtensionDataIsJToken; private bool? _hasRequiredOrDefaultValueProperties; private ObjectConstructor? _overrideCreator; private ObjectConstructor? _parameterizedCreator; private JsonPropertyCollection? _creatorParameters; private Type? _extensionDataValueType; public MemberSerialization MemberSerialization { get; set; } public MissingMemberHandling? MissingMemberHandling { get; set; } public Required? ItemRequired { get; set; } public NullValueHandling? ItemNullValueHandling { get; set; } public JsonPropertyCollection Properties { get; } public JsonPropertyCollection CreatorParameters { get { if (_creatorParameters == null) { _creatorParameters = new JsonPropertyCollection(base.UnderlyingType); } return _creatorParameters; } } public ObjectConstructor? OverrideCreator { get { return _overrideCreator; } set { _overrideCreator = value; } } internal ObjectConstructor? ParameterizedCreator { get { return _parameterizedCreator; } set { _parameterizedCreator = value; } } public ExtensionDataSetter? ExtensionDataSetter { get; set; } public ExtensionDataGetter? ExtensionDataGetter { get; set; } public Type? ExtensionDataValueType { get { return _extensionDataValueType; } set { _extensionDataValueType = value; ExtensionDataIsJToken = value != null && typeof(JToken).IsAssignableFrom(value); } } public Func? ExtensionDataNameResolver { get; set; } internal bool HasRequiredOrDefaultValueProperties { get { if (!_hasRequiredOrDefaultValueProperties.HasValue) { _hasRequiredOrDefaultValueProperties = false; if (ItemRequired.GetValueOrDefault(Required.Default) != 0) { _hasRequiredOrDefaultValueProperties = true; } else { foreach (JsonProperty property in Properties) { if (property.Required != 0 || ((uint?)property.DefaultValueHandling & 2u) == 2) { _hasRequiredOrDefaultValueProperties = true; break; } } } } return _hasRequiredOrDefaultValueProperties.GetValueOrDefault(); } } public JsonObjectContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Object; Properties = new JsonPropertyCollection(base.UnderlyingType); } [SecuritySafeCritical] internal object GetUninitializedObject() { if (!JsonTypeReflector.FullyTrusted) { throw new JsonException("Insufficient permissions. Creating an uninitialized '{0}' type requires full trust.".FormatWith(CultureInfo.InvariantCulture, NonNullableUnderlyingType)); } return FormatterServices.GetUninitializedObject(NonNullableUnderlyingType); } } internal class JsonPrimitiveContract : JsonContract { private static readonly Dictionary ReadTypeMap = new Dictionary { [typeof(byte[])] = ReadType.ReadAsBytes, [typeof(byte)] = ReadType.ReadAsInt32, [typeof(short)] = ReadType.ReadAsInt32, [typeof(int)] = ReadType.ReadAsInt32, [typeof(decimal)] = ReadType.ReadAsDecimal, [typeof(bool)] = ReadType.ReadAsBoolean, [typeof(string)] = ReadType.ReadAsString, [typeof(DateTime)] = ReadType.ReadAsDateTime, [typeof(DateTimeOffset)] = ReadType.ReadAsDateTimeOffset, [typeof(float)] = ReadType.ReadAsDouble, [typeof(double)] = ReadType.ReadAsDouble, [typeof(long)] = ReadType.ReadAsInt64 }; internal PrimitiveTypeCode TypeCode { get; set; } public JsonPrimitiveContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.Primitive; TypeCode = ConvertUtils.GetTypeCode(underlyingType); IsReadOnlyOrFixedSize = true; if (ReadTypeMap.TryGetValue(NonNullableUnderlyingType, out var value)) { InternalReadType = value; } } } internal class JsonProperty { internal Required? _required; internal bool _hasExplicitDefaultValue; private object? _defaultValue; private bool _hasGeneratedDefaultValue; private string? _propertyName; internal bool _skipPropertyNameEscape; private Type? _propertyType; internal JsonContract? PropertyContract { get; set; } public string? PropertyName { get { return _propertyName; } set { _propertyName = value; _skipPropertyNameEscape = !JavaScriptUtils.ShouldEscapeJavaScriptString(_propertyName, JavaScriptUtils.HtmlCharEscapeFlags); } } public Type? DeclaringType { get; set; } public int? Order { get; set; } public string? UnderlyingName { get; set; } public IValueProvider? ValueProvider { get; set; } public IAttributeProvider? AttributeProvider { get; set; } public Type? PropertyType { get { return _propertyType; } set { if (_propertyType != value) { _propertyType = value; _hasGeneratedDefaultValue = false; } } } public JsonConverter? Converter { get; set; } [Obsolete("MemberConverter is obsolete. Use Converter instead.")] public JsonConverter? MemberConverter { get { return Converter; } set { Converter = value; } } public bool Ignored { get; set; } public bool Readable { get; set; } public bool Writable { get; set; } public bool HasMemberAttribute { get; set; } public object? DefaultValue { get { if (!_hasExplicitDefaultValue) { return null; } return _defaultValue; } set { _hasExplicitDefaultValue = true; _defaultValue = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public bool IsRequiredSpecified => _required.HasValue; public bool? IsReference { get; set; } public NullValueHandling? NullValueHandling { get; set; } public DefaultValueHandling? DefaultValueHandling { get; set; } public ReferenceLoopHandling? ReferenceLoopHandling { get; set; } public ObjectCreationHandling? ObjectCreationHandling { get; set; } public TypeNameHandling? TypeNameHandling { get; set; } public Predicate? ShouldSerialize { get; set; } public Predicate? ShouldDeserialize { get; set; } public Predicate? GetIsSpecified { get; set; } public Action? SetIsSpecified { get; set; } public JsonConverter? ItemConverter { get; set; } public bool? ItemIsReference { get; set; } public TypeNameHandling? ItemTypeNameHandling { get; set; } public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; } internal object? GetResolvedDefaultValue() { if (_propertyType == null) { return null; } if (!_hasExplicitDefaultValue && !_hasGeneratedDefaultValue) { _defaultValue = ReflectionUtils.GetDefaultValue(_propertyType); _hasGeneratedDefaultValue = true; } return _defaultValue; } public override string ToString() { return PropertyName ?? string.Empty; } internal void WritePropertyName(JsonWriter writer) { string propertyName = PropertyName; if (_skipPropertyNameEscape) { writer.WritePropertyName(propertyName, escape: false); } else { writer.WritePropertyName(propertyName); } } } internal class JsonPropertyCollection : KeyedCollection { private readonly Type _type; private readonly List _list; public JsonPropertyCollection(Type type) : base((IEqualityComparer?)StringComparer.Ordinal) { ValidationUtils.ArgumentNotNull(type, "type"); _type = type; _list = (List)base.Items; } protected override string GetKeyForItem(JsonProperty item) { return item.PropertyName; } public void AddProperty(JsonProperty property) { if (Contains(property.PropertyName)) { if (property.Ignored) { return; } JsonProperty jsonProperty = base[property.PropertyName]; bool flag = true; if (jsonProperty.Ignored) { Remove(jsonProperty); flag = false; } else if (property.DeclaringType != null && jsonProperty.DeclaringType != null) { if (property.DeclaringType.IsSubclassOf(jsonProperty.DeclaringType) || (jsonProperty.DeclaringType.IsInterface() && property.DeclaringType.ImplementInterface(jsonProperty.DeclaringType))) { Remove(jsonProperty); flag = false; } if (jsonProperty.DeclaringType.IsSubclassOf(property.DeclaringType) || (property.DeclaringType.IsInterface() && jsonProperty.DeclaringType.ImplementInterface(property.DeclaringType)) || (_type.ImplementInterface(jsonProperty.DeclaringType) && _type.ImplementInterface(property.DeclaringType))) { return; } } if (flag) { throw new JsonSerializationException("A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, _type)); } } Add(property); } public JsonProperty? GetClosestMatchProperty(string propertyName) { JsonProperty property = GetProperty(propertyName, StringComparison.Ordinal); if (property == null) { property = GetProperty(propertyName, StringComparison.OrdinalIgnoreCase); } return property; } private bool TryGetProperty(string key, [NotNullWhen(true)] out JsonProperty? item) { if (base.Dictionary == null) { item = null; return false; } return base.Dictionary.TryGetValue(key, out item); } public JsonProperty? GetProperty(string propertyName, StringComparison comparisonType) { if (comparisonType == StringComparison.Ordinal) { if (TryGetProperty(propertyName, out JsonProperty item)) { return item; } return null; } for (int i = 0; i < _list.Count; i++) { JsonProperty jsonProperty = _list[i]; if (string.Equals(propertyName, jsonProperty.PropertyName, comparisonType)) { return jsonProperty; } } return null; } } internal abstract class JsonSerializerInternalBase { private class ReferenceEqualsEqualityComparer : IEqualityComparer { bool IEqualityComparer.Equals(object? x, object? y) { return x == y; } int IEqualityComparer.GetHashCode(object obj) { return RuntimeHelpers.GetHashCode(obj); } } private ErrorContext? _currentErrorContext; private BidirectionalDictionary? _mappings; internal readonly JsonSerializer Serializer; internal readonly ITraceWriter? TraceWriter; protected JsonSerializerProxy? InternalSerializer; internal BidirectionalDictionary DefaultReferenceMappings { get { if (_mappings == null) { _mappings = new BidirectionalDictionary(EqualityComparer.Default, new ReferenceEqualsEqualityComparer(), "A different value already has the Id '{0}'.", "A different Id has already been assigned for value '{0}'. This error may be caused by an object being reused multiple times during deserialization and can be fixed with the setting ObjectCreationHandling.Replace."); } return _mappings; } } protected JsonSerializerInternalBase(JsonSerializer serializer) { ValidationUtils.ArgumentNotNull(serializer, "serializer"); Serializer = serializer; TraceWriter = serializer.TraceWriter; } protected NullValueHandling ResolvedNullValueHandling(JsonObjectContract? containerContract, JsonProperty property) { return property.NullValueHandling ?? containerContract?.ItemNullValueHandling ?? Serializer._nullValueHandling; } private ErrorContext GetErrorContext(object? currentObject, object? member, string path, Exception error) { if (_currentErrorContext == null) { _currentErrorContext = new ErrorContext(currentObject, member, path, error); } if (_currentErrorContext.Error != error) { throw new InvalidOperationException("Current error context error is different to requested error."); } return _currentErrorContext; } protected void ClearErrorContext() { if (_currentErrorContext == null) { throw new InvalidOperationException("Could not clear error context. Error context is already null."); } _currentErrorContext = null; } protected bool IsErrorHandled(object? currentObject, JsonContract? contract, object? keyValue, IJsonLineInfo? lineInfo, string path, Exception ex) { ErrorContext errorContext = GetErrorContext(currentObject, keyValue, path, ex); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Error && !errorContext.Traced) { errorContext.Traced = true; string text = ((GetType() == typeof(JsonSerializerInternalWriter)) ? "Error serializing" : "Error deserializing"); if (contract != null) { text = text + " " + contract.UnderlyingType; } text = text + ". " + ex.Message; if (!(ex is JsonException)) { text = JsonPosition.FormatMessage(lineInfo, path, text); } TraceWriter.Trace(TraceLevel.Error, text, ex); } if (contract != null && currentObject != null) { contract.InvokeOnError(currentObject, Serializer.Context, errorContext); } if (!errorContext.Handled) { Serializer.OnError(new ErrorEventArgs(currentObject, errorContext)); } return errorContext.Handled; } } internal class JsonSerializerInternalReader : JsonSerializerInternalBase { internal enum PropertyPresence { None, Null, Value } internal class CreatorPropertyContext { public readonly string Name; public JsonProperty? Property; public JsonProperty? ConstructorProperty; public PropertyPresence? Presence; public object? Value; public bool Used; public CreatorPropertyContext(string name) { Name = name; } } public JsonSerializerInternalReader(JsonSerializer serializer) : base(serializer) { } public void Populate(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(target, "target"); Type type = target.GetType(); JsonContract jsonContract = Serializer._contractResolver.ResolveContract(type); if (!reader.MoveToContent()) { throw JsonSerializationException.Create(reader, "No JSON content found."); } if (reader.TokenType == JsonToken.StartArray) { if (jsonContract.ContractType == JsonContractType.Array) { JsonArrayContract jsonArrayContract = (JsonArrayContract)jsonContract; object list; if (!jsonArrayContract.ShouldCreateWrapper) { list = (IList)target; } else { IList list2 = jsonArrayContract.CreateWrapper(target); list = list2; } PopulateList((IList)list, reader, jsonArrayContract, null, null); return; } throw JsonSerializationException.Create(reader, "Cannot populate JSON array onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, type)); } if (reader.TokenType == JsonToken.StartObject) { reader.ReadAndAssert(); string id = null; if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore && reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), "$id", StringComparison.Ordinal)) { reader.ReadAndAssert(); id = reader.Value?.ToString(); reader.ReadAndAssert(); } if (jsonContract.ContractType == JsonContractType.Dictionary) { JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)jsonContract; object dictionary; if (!jsonDictionaryContract.ShouldCreateWrapper) { dictionary = (IDictionary)target; } else { IDictionary dictionary2 = jsonDictionaryContract.CreateWrapper(target); dictionary = dictionary2; } PopulateDictionary((IDictionary)dictionary, reader, jsonDictionaryContract, null, id); } else { if (jsonContract.ContractType != JsonContractType.Object) { throw JsonSerializationException.Create(reader, "Cannot populate JSON object onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, type)); } PopulateObject(target, reader, (JsonObjectContract)jsonContract, null, id); } return; } throw JsonSerializationException.Create(reader, "Unexpected initial token '{0}' when populating object. Expected JSON object or array.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } private JsonContract? GetContractSafe(Type? type) { if (type == null) { return null; } return GetContract(type); } private JsonContract GetContract(Type type) { return Serializer._contractResolver.ResolveContract(type); } public object? Deserialize(JsonReader reader, Type? objectType, bool checkAdditionalContent) { if (reader == null) { throw new ArgumentNullException("reader"); } JsonContract contractSafe = GetContractSafe(objectType); try { JsonConverter converter = GetConverter(contractSafe, null, null, null); if (reader.TokenType == JsonToken.None && !reader.ReadForType(contractSafe, converter != null)) { if (contractSafe != null && !contractSafe.IsNullable) { throw JsonSerializationException.Create(reader, "No JSON content found and type '{0}' is not nullable.".FormatWith(CultureInfo.InvariantCulture, contractSafe.UnderlyingType)); } return null; } object result = ((converter == null || !converter.CanRead) ? CreateValueInternal(reader, objectType, contractSafe, null, null, null, null) : DeserializeConvertable(converter, reader, objectType, null)); if (checkAdditionalContent) { while (reader.Read()) { if (reader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(reader, "Additional text found in JSON string after finishing deserializing object."); } } } return result; } catch (Exception ex) { if (IsErrorHandled(null, contractSafe, null, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: false, 0); return null; } ClearErrorContext(); throw; } } private JsonSerializerProxy GetInternalSerializer() { if (InternalSerializer == null) { InternalSerializer = new JsonSerializerProxy(this); } return InternalSerializer; } private JToken? CreateJToken(JsonReader reader, JsonContract? contract) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (contract != null) { if (contract.UnderlyingType == typeof(JRaw)) { return JRaw.Create(reader); } if (reader.TokenType == JsonToken.Null && !(contract.UnderlyingType == typeof(JValue)) && !(contract.UnderlyingType == typeof(JToken))) { return null; } } JToken token; using (JTokenWriter jTokenWriter = new JTokenWriter()) { jTokenWriter.WriteToken(reader); token = jTokenWriter.Token; } if (contract != null && token != null && !contract.UnderlyingType.IsAssignableFrom(token.GetType())) { throw JsonSerializationException.Create(reader, "Deserialized JSON type '{0}' is not compatible with expected type '{1}'.".FormatWith(CultureInfo.InvariantCulture, token.GetType().FullName, contract.UnderlyingType.FullName)); } return token; } private JToken CreateJObject(JsonReader reader) { ValidationUtils.ArgumentNotNull(reader, "reader"); using JTokenWriter jTokenWriter = new JTokenWriter(); jTokenWriter.WriteStartObject(); do { if (reader.TokenType == JsonToken.PropertyName) { string text = (string)reader.Value; if (!reader.ReadAndMoveToContent()) { break; } if (!CheckPropertyName(reader, text)) { jTokenWriter.WritePropertyName(text); jTokenWriter.WriteToken(reader, writeChildren: true, writeDateConstructorAsDate: true, writeComments: false); } } else if (reader.TokenType != JsonToken.Comment) { jTokenWriter.WriteEndObject(); return jTokenWriter.Token; } } while (reader.Read()); throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } private object? CreateValueInternal(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue) { if (contract != null && contract.ContractType == JsonContractType.Linq) { return CreateJToken(reader, contract); } do { switch (reader.TokenType) { case JsonToken.StartObject: return CreateObject(reader, objectType, contract, member, containerContract, containerMember, existingValue); case JsonToken.StartArray: return CreateList(reader, objectType, contract, member, existingValue, null); case JsonToken.Integer: case JsonToken.Float: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.String: { string text = (string)reader.Value; if (objectType == typeof(byte[])) { return Convert.FromBase64String(text); } if (CoerceEmptyStringToNull(objectType, contract, text)) { return null; } return EnsureType(reader, text, CultureInfo.InvariantCulture, contract, objectType); } case JsonToken.StartConstructor: { string value = reader.Value.ToString(); return EnsureType(reader, value, CultureInfo.InvariantCulture, contract, objectType); } case JsonToken.Null: case JsonToken.Undefined: if (objectType == typeof(DBNull)) { return DBNull.Value; } return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType); case JsonToken.Raw: return new JRaw((string)reader.Value); default: throw JsonSerializationException.Create(reader, "Unexpected token while deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (reader.Read()); throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } private static bool CoerceEmptyStringToNull(Type? objectType, JsonContract? contract, string s) { if (StringUtils.IsNullOrEmpty(s) && objectType != null && objectType != typeof(string) && objectType != typeof(object) && contract != null) { return contract.IsNullable; } return false; } internal string GetExpectedDescription(JsonContract contract) { switch (contract.ContractType) { case JsonContractType.Object: case JsonContractType.Dictionary: case JsonContractType.Dynamic: case JsonContractType.Serializable: return "JSON object (e.g. {\"name\":\"value\"})"; case JsonContractType.Array: return "JSON array (e.g. [1,2,3])"; case JsonContractType.Primitive: return "JSON primitive value (e.g. string, number, boolean, null)"; case JsonContractType.String: return "JSON string value"; default: throw new ArgumentOutOfRangeException(); } } private JsonConverter? GetConverter(JsonContract? contract, JsonConverter? memberConverter, JsonContainerContract? containerContract, JsonProperty? containerProperty) { JsonConverter result = null; if (memberConverter != null) { result = memberConverter; } else if (containerProperty?.ItemConverter != null) { result = containerProperty.ItemConverter; } else if (containerContract?.ItemConverter != null) { result = containerContract.ItemConverter; } else if (contract != null) { if (contract.Converter != null) { result = contract.Converter; } else { JsonConverter matchingConverter = Serializer.GetMatchingConverter(contract.UnderlyingType); if (matchingConverter != null) { result = matchingConverter; } else if (contract.InternalConverter != null) { result = contract.InternalConverter; } } } return result; } private object? CreateObject(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue) { Type objectType2 = objectType; string id; if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.Ignore) { reader.ReadAndAssert(); id = null; } else if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead) { JTokenReader jTokenReader = reader as JTokenReader; if (jTokenReader == null) { jTokenReader = (JTokenReader)JToken.ReadFrom(reader).CreateReader(); jTokenReader.Culture = reader.Culture; jTokenReader.DateFormatString = reader.DateFormatString; jTokenReader.DateParseHandling = reader.DateParseHandling; jTokenReader.DateTimeZoneHandling = reader.DateTimeZoneHandling; jTokenReader.FloatParseHandling = reader.FloatParseHandling; jTokenReader.SupportMultipleContent = reader.SupportMultipleContent; jTokenReader.ReadAndAssert(); reader = jTokenReader; } if (ReadMetadataPropertiesToken(jTokenReader, ref objectType2, ref contract, member, containerContract, containerMember, existingValue, out object newValue, out id)) { return newValue; } } else { reader.ReadAndAssert(); if (ReadMetadataProperties(reader, ref objectType2, ref contract, member, containerContract, containerMember, existingValue, out object newValue2, out id)) { return newValue2; } } if (HasNoDefinedType(contract)) { return CreateJObject(reader); } switch (contract.ContractType) { case JsonContractType.Object: { bool createdFromNonDefaultCreator2 = false; JsonObjectContract jsonObjectContract = (JsonObjectContract)contract; object obj = ((existingValue == null || (!(objectType2 == objectType) && !objectType2.IsAssignableFrom(existingValue.GetType()))) ? CreateNewObject(reader, jsonObjectContract, member, containerMember, id, out createdFromNonDefaultCreator2) : existingValue); if (createdFromNonDefaultCreator2) { return obj; } return PopulateObject(obj, reader, jsonObjectContract, member, id); } case JsonContractType.Primitive: { JsonPrimitiveContract contract4 = (JsonPrimitiveContract)contract; if (Serializer.MetadataPropertyHandling != MetadataPropertyHandling.Ignore && reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), "$value", StringComparison.Ordinal)) { reader.ReadAndAssert(); if (reader.TokenType == JsonToken.StartObject) { throw JsonSerializationException.Create(reader, "Unexpected token when deserializing primitive value: " + reader.TokenType); } object? result = CreateValueInternal(reader, objectType2, contract4, member, null, null, existingValue); reader.ReadAndAssert(); return result; } break; } case JsonContractType.Dictionary: { JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)contract; if (existingValue == null) { bool createdFromNonDefaultCreator; IDictionary dictionary = CreateNewDictionary(reader, jsonDictionaryContract, out createdFromNonDefaultCreator); if (createdFromNonDefaultCreator) { if (id != null) { throw JsonSerializationException.Create(reader, "Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.OnSerializingCallbacks.Count > 0) { throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.OnErrorCallbacks.Count > 0) { throw JsonSerializationException.Create(reader, "Cannot call OnError on readonly list, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (!jsonDictionaryContract.HasParameterizedCreatorInternal) { throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } } PopulateDictionary(dictionary, reader, jsonDictionaryContract, member, id); if (createdFromNonDefaultCreator) { return (jsonDictionaryContract.OverrideCreator ?? jsonDictionaryContract.ParameterizedCreator)(dictionary); } if (dictionary is IWrappedDictionary wrappedDictionary) { return wrappedDictionary.UnderlyingDictionary; } return dictionary; } object dictionary2; if (!jsonDictionaryContract.ShouldCreateWrapper && existingValue is IDictionary) { dictionary2 = (IDictionary)existingValue; } else { IDictionary dictionary3 = jsonDictionaryContract.CreateWrapper(existingValue); dictionary2 = dictionary3; } return PopulateDictionary((IDictionary)dictionary2, reader, jsonDictionaryContract, member, id); } case JsonContractType.Dynamic: { JsonDynamicContract contract3 = (JsonDynamicContract)contract; return CreateDynamic(reader, contract3, member, id); } case JsonContractType.Serializable: { JsonISerializableContract contract2 = (JsonISerializableContract)contract; return CreateISerializable(reader, contract2, member, id); } } string format = "Cannot deserialize the current JSON object (e.g. {{\"name\":\"value\"}}) into type '{0}' because the type requires a {1} to deserialize correctly." + Environment.NewLine + "To fix this error either change the JSON to a {1} or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object." + Environment.NewLine; format = format.FormatWith(CultureInfo.InvariantCulture, objectType2, GetExpectedDescription(contract)); throw JsonSerializationException.Create(reader, format); } private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, out object? newValue, out string? id) { id = null; newValue = null; if (reader.TokenType == JsonToken.StartObject) { JObject jObject = (JObject)reader.CurrentToken; JProperty jProperty = jObject.Property("$ref", StringComparison.Ordinal); if (jProperty != null) { JToken value = jProperty.Value; if (value.Type != JTokenType.String && value.Type != JTokenType.Null) { throw JsonSerializationException.Create(value, value.Path, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, "$ref"), null); } string text = (string?)(JToken?)jProperty; if (text != null) { JToken jToken = jProperty.Next ?? jProperty.Previous; if (jToken != null) { throw JsonSerializationException.Create(jToken, jToken.Path, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, "$ref"), null); } newValue = Serializer.GetReferenceResolver().ResolveReference(this, text); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, text, newValue.GetType())), null); } reader.Skip(); return true; } } JToken jToken2 = jObject["$type"]; if (jToken2 != null) { string qualifiedTypeName = (string?)jToken2; JsonReader jsonReader = jToken2.CreateReader(); jsonReader.ReadAndAssert(); ResolveTypeName(jsonReader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); if (jObject["$value"] != null) { while (true) { reader.ReadAndAssert(); if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "$value") { break; } reader.ReadAndAssert(); reader.Skip(); } return false; } } JToken jToken3 = jObject["$id"]; if (jToken3 != null) { id = (string?)jToken3; } JToken jToken4 = jObject["$values"]; if (jToken4 != null) { JsonReader jsonReader2 = jToken4.CreateReader(); jsonReader2.ReadAndAssert(); newValue = CreateList(jsonReader2, objectType, contract, member, existingValue, id); reader.Skip(); return true; } } reader.ReadAndAssert(); return false; } private bool ReadMetadataProperties(JsonReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, object? existingValue, out object? newValue, out string? id) { id = null; newValue = null; if (reader.TokenType == JsonToken.PropertyName) { string text = reader.Value.ToString(); if (text.Length > 0 && text[0] == '$') { bool flag; do { text = reader.Value.ToString(); if (string.Equals(text, "$ref", StringComparison.Ordinal)) { reader.ReadAndAssert(); if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Null) { throw JsonSerializationException.Create(reader, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, "$ref")); } string text2 = reader.Value?.ToString(); reader.ReadAndAssert(); if (text2 != null) { if (reader.TokenType == JsonToken.PropertyName) { throw JsonSerializationException.Create(reader, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, "$ref")); } newValue = Serializer.GetReferenceResolver().ResolveReference(this, text2); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, text2, newValue.GetType())), null); } return true; } flag = true; } else if (string.Equals(text, "$type", StringComparison.Ordinal)) { reader.ReadAndAssert(); string qualifiedTypeName = reader.Value.ToString(); ResolveTypeName(reader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName); reader.ReadAndAssert(); flag = true; } else if (string.Equals(text, "$id", StringComparison.Ordinal)) { reader.ReadAndAssert(); id = reader.Value?.ToString(); reader.ReadAndAssert(); flag = true; } else { if (string.Equals(text, "$values", StringComparison.Ordinal)) { reader.ReadAndAssert(); object obj = CreateList(reader, objectType, contract, member, existingValue, id); reader.ReadAndAssert(); newValue = obj; return true; } flag = false; } } while (flag && reader.TokenType == JsonToken.PropertyName); } } return false; } private void ResolveTypeName(JsonReader reader, ref Type? objectType, ref JsonContract? contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerMember, string qualifiedTypeName) { if ((member?.TypeNameHandling ?? containerContract?.ItemTypeNameHandling ?? containerMember?.ItemTypeNameHandling ?? Serializer._typeNameHandling) != 0) { StructMultiKey structMultiKey = ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName); Type type; try { type = Serializer._serializationBinder.BindToType(structMultiKey.Value1, structMultiKey.Value2); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error resolving type specified in JSON '{0}'.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName), ex); } if (type == null) { throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName)); } if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved type '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName, type)), null); } if (objectType != null && objectType != typeof(IDynamicMetaObjectProvider) && !objectType.IsAssignableFrom(type)) { throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, type.AssemblyQualifiedName, objectType.AssemblyQualifiedName)); } objectType = type; contract = GetContract(type); } } private JsonArrayContract EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract) { if (contract == null) { throw JsonSerializationException.Create(reader, "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType)); } JsonArrayContract obj = contract as JsonArrayContract; if (obj == null) { string format = "Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '{0}' because the type requires a {1} to deserialize correctly." + Environment.NewLine + "To fix this error either change the JSON to a {1} or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array." + Environment.NewLine; format = format.FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract)); throw JsonSerializationException.Create(reader, format); } return obj; } private object? CreateList(JsonReader reader, Type? objectType, JsonContract? contract, JsonProperty? member, object? existingValue, string? id) { if (HasNoDefinedType(contract)) { return CreateJToken(reader, contract); } JsonArrayContract jsonArrayContract = EnsureArrayContract(reader, objectType, contract); if (existingValue == null) { bool createdFromNonDefaultCreator; IList list = CreateNewList(reader, jsonArrayContract, out createdFromNonDefaultCreator); if (createdFromNonDefaultCreator) { if (id != null) { throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.OnSerializingCallbacks.Count > 0) { throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.OnErrorCallbacks.Count > 0) { throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (!jsonArrayContract.HasParameterizedCreatorInternal && !jsonArrayContract.IsArray) { throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } } if (!jsonArrayContract.IsMultidimensionalArray) { PopulateList(list, reader, jsonArrayContract, member, id); } else { PopulateMultidimensionalArray(list, reader, jsonArrayContract, member, id); } if (createdFromNonDefaultCreator) { if (jsonArrayContract.IsMultidimensionalArray) { list = CollectionUtils.ToMultidimensionalArray(list, jsonArrayContract.CollectionItemType, contract.CreatedType.GetArrayRank()); } else { if (!jsonArrayContract.IsArray) { return (jsonArrayContract.OverrideCreator ?? jsonArrayContract.ParameterizedCreator)(list); } Array array = Array.CreateInstance(jsonArrayContract.CollectionItemType, list.Count); list.CopyTo(array, 0); list = array; } } else if (list is IWrappedCollection wrappedCollection) { return wrappedCollection.UnderlyingCollection; } return list; } if (!jsonArrayContract.CanDeserialize) { throw JsonSerializationException.Create(reader, "Cannot populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType)); } IList list3; if (!jsonArrayContract.ShouldCreateWrapper && existingValue is IList list2) { list3 = list2; } else { IList list4 = jsonArrayContract.CreateWrapper(existingValue); list3 = list4; } return PopulateList(list3, reader, jsonArrayContract, member, id); } private bool HasNoDefinedType(JsonContract? contract) { if (contract != null && !(contract.UnderlyingType == typeof(object)) && contract.ContractType != JsonContractType.Linq) { return contract.UnderlyingType == typeof(IDynamicMetaObjectProvider); } return true; } private object? EnsureType(JsonReader reader, object? value, CultureInfo culture, JsonContract? contract, Type? targetType) { if (targetType == null) { return value; } if (ReflectionUtils.GetObjectType(value) != targetType) { if (value == null && contract.IsNullable) { return null; } try { if (contract.IsConvertable) { JsonPrimitiveContract jsonPrimitiveContract = (JsonPrimitiveContract)contract; DateTime dt; if (contract.IsEnum) { if (value is string value2) { return EnumUtils.ParseEnum(contract.NonNullableUnderlyingType, null, value2, disallowNumber: false); } if (ConvertUtils.IsInteger(jsonPrimitiveContract.TypeCode)) { return Enum.ToObject(contract.NonNullableUnderlyingType, value); } } else if (contract.NonNullableUnderlyingType == typeof(DateTime) && value is string s && DateTimeUtils.TryParseDateTime(s, reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out dt)) { return DateTimeUtils.EnsureDateTime(dt, reader.DateTimeZoneHandling); } if (value is BigInteger i) { return ConvertUtils.FromBigInteger(i, contract.NonNullableUnderlyingType); } return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture); } return ConvertUtils.ConvertOrCast(value, culture, contract.NonNullableUnderlyingType); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(value), targetType), ex); } } return value; } private bool SetPropertyValue(JsonProperty property, JsonConverter? propertyConverter, JsonContainerContract? containerContract, JsonProperty? containerProperty, JsonReader reader, object target) { if (CalculatePropertyDetails(property, ref propertyConverter, containerContract, containerProperty, reader, target, out bool useExistingValue, out object currentValue, out JsonContract propertyContract, out bool gottenCurrentValue, out bool ignoredValue)) { if (ignoredValue) { return true; } return false; } object obj; if (propertyConverter != null && propertyConverter.CanRead) { if (!gottenCurrentValue && property.Readable) { currentValue = property.ValueProvider.GetValue(target); } obj = DeserializeConvertable(propertyConverter, reader, property.PropertyType, currentValue); } else { obj = CreateValueInternal(reader, property.PropertyType, propertyContract, property, containerContract, containerProperty, useExistingValue ? currentValue : null); } if ((!useExistingValue || obj != currentValue) && ShouldSetPropertyValue(property, containerContract as JsonObjectContract, obj)) { property.ValueProvider.SetValue(target, obj); if (property.SetIsSpecified != null) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "IsSpecified for property '{0}' on {1} set to true.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType)), null); } property.SetIsSpecified(target, true); } return true; } return useExistingValue; } private bool CalculatePropertyDetails(JsonProperty property, ref JsonConverter? propertyConverter, JsonContainerContract? containerContract, JsonProperty? containerProperty, JsonReader reader, object target, out bool useExistingValue, out object? currentValue, out JsonContract? propertyContract, out bool gottenCurrentValue, out bool ignoredValue) { currentValue = null; useExistingValue = false; propertyContract = null; gottenCurrentValue = false; ignoredValue = false; if (property.Ignored) { return true; } JsonToken tokenType = reader.TokenType; if (property.PropertyContract == null) { property.PropertyContract = GetContractSafe(property.PropertyType); } if (property.ObjectCreationHandling.GetValueOrDefault(Serializer._objectCreationHandling) != ObjectCreationHandling.Replace && (tokenType == JsonToken.StartArray || tokenType == JsonToken.StartObject || propertyConverter != null) && property.Readable) { JsonContract? propertyContract2 = property.PropertyContract; if (propertyContract2 == null || propertyContract2.ContractType != JsonContractType.Linq) { currentValue = property.ValueProvider.GetValue(target); gottenCurrentValue = true; if (currentValue != null) { propertyContract = GetContract(currentValue.GetType()); useExistingValue = !propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType(); } } } if (!property.Writable && !useExistingValue) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Unable to deserialize value to non-writable property '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType)), null); } return true; } if (tokenType == JsonToken.Null && ResolvedNullValueHandling(containerContract as JsonObjectContract, property) == NullValueHandling.Ignore) { ignoredValue = true; return true; } if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && JsonTokenUtils.IsPrimitiveToken(tokenType) && MiscellaneousUtils.ValueEquals(reader.Value, property.GetResolvedDefaultValue())) { ignoredValue = true; return true; } if (currentValue == null) { propertyContract = property.PropertyContract; } else { propertyContract = GetContract(currentValue.GetType()); if (propertyContract != property.PropertyContract) { propertyConverter = GetConverter(propertyContract, property.Converter, containerContract, containerProperty); } } return false; } private void AddReference(JsonReader reader, string id, object value) { try { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Read object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, id, value.GetType())), null); } Serializer.GetReferenceResolver().AddReference(this, id, value); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error reading object reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, id), ex); } } private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) { return (value & flag) == flag; } private bool ShouldSetPropertyValue(JsonProperty property, JsonObjectContract? contract, object? value) { if (value == null && ResolvedNullValueHandling(contract, property) == NullValueHandling.Ignore) { return false; } if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && MiscellaneousUtils.ValueEquals(value, property.GetResolvedDefaultValue())) { return false; } if (!property.Writable) { return false; } return true; } private IList CreateNewList(JsonReader reader, JsonArrayContract contract, out bool createdFromNonDefaultCreator) { if (!contract.CanDeserialize) { throw JsonSerializationException.Create(reader, "Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType)); } if (contract.OverrideCreator != null) { if (contract.HasParameterizedCreator) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryCollection(); } object obj = contract.OverrideCreator(); if (contract.ShouldCreateWrapper) { obj = contract.CreateWrapper(obj); } createdFromNonDefaultCreator = false; return (IList)obj; } if (contract.IsReadOnlyOrFixedSize) { createdFromNonDefaultCreator = true; IList list = contract.CreateTemporaryCollection(); if (contract.ShouldCreateWrapper) { list = contract.CreateWrapper(list); } return list; } if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) { object obj2 = contract.DefaultCreator(); if (contract.ShouldCreateWrapper) { obj2 = contract.CreateWrapper(obj2); } createdFromNonDefaultCreator = false; return (IList)obj2; } if (contract.HasParameterizedCreatorInternal) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryCollection(); } if (!contract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } private IDictionary CreateNewDictionary(JsonReader reader, JsonDictionaryContract contract, out bool createdFromNonDefaultCreator) { if (contract.OverrideCreator != null) { if (contract.HasParameterizedCreator) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryDictionary(); } createdFromNonDefaultCreator = false; return (IDictionary)contract.OverrideCreator(); } if (contract.IsReadOnlyOrFixedSize) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryDictionary(); } if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) { object obj = contract.DefaultCreator(); if (contract.ShouldCreateWrapper) { obj = contract.CreateWrapper(obj); } createdFromNonDefaultCreator = false; return (IDictionary)obj; } if (contract.HasParameterizedCreatorInternal) { createdFromNonDefaultCreator = true; return contract.CreateTemporaryDictionary(); } if (!contract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } private void OnDeserializing(JsonReader reader, JsonContract contract, object value) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } contract.InvokeOnDeserializing(value, Serializer._context); } private void OnDeserialized(JsonReader reader, JsonContract contract, object value) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Finished deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } contract.InvokeOnDeserialized(value, Serializer._context); } private object PopulateDictionary(IDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty? containerProperty, string? id) { object obj = ((dictionary is IWrappedDictionary wrappedDictionary) ? wrappedDictionary.UnderlyingDictionary : dictionary); if (id != null) { AddReference(reader, id, obj); } OnDeserializing(reader, contract, obj); int depth = reader.Depth; if (contract.KeyContract == null) { contract.KeyContract = GetContractSafe(contract.DictionaryKeyType); } if (contract.ItemContract == null) { contract.ItemContract = GetContractSafe(contract.DictionaryValueType); } JsonConverter jsonConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty); PrimitiveTypeCode primitiveTypeCode = ((contract.KeyContract is JsonPrimitiveContract jsonPrimitiveContract) ? jsonPrimitiveContract.TypeCode : PrimitiveTypeCode.Empty); bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { object obj2 = reader.Value; if (CheckPropertyName(reader, obj2.ToString())) { break; } try { try { switch (primitiveTypeCode) { case PrimitiveTypeCode.DateTime: case PrimitiveTypeCode.DateTimeNullable: { obj2 = (DateTimeUtils.TryParseDateTime(obj2.ToString(), reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out var dt2) ? ((object)dt2) : EnsureType(reader, obj2, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)); break; } case PrimitiveTypeCode.DateTimeOffset: case PrimitiveTypeCode.DateTimeOffsetNullable: { obj2 = (DateTimeUtils.TryParseDateTimeOffset(obj2.ToString(), reader.DateFormatString, reader.Culture, out var dt) ? ((object)dt) : EnsureType(reader, obj2, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)); break; } default: obj2 = ((contract.KeyContract != null && contract.KeyContract.IsEnum) ? EnumUtils.ParseEnum(contract.KeyContract.NonNullableUnderlyingType, (Serializer._contractResolver as DefaultContractResolver)?.NamingStrategy, obj2.ToString(), disallowNumber: false) : EnsureType(reader, obj2, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType)); break; } } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Could not convert string '{0}' to dictionary key type '{1}'. Create a TypeConverter to convert from the string to the key type object.".FormatWith(CultureInfo.InvariantCulture, reader.Value, contract.DictionaryKeyType), ex); } if (!reader.ReadForType(contract.ItemContract, jsonConverter != null)) { throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object."); } object value = ((jsonConverter == null || !jsonConverter.CanRead) ? CreateValueInternal(reader, contract.DictionaryValueType, contract.ItemContract, null, contract, containerProperty, null) : DeserializeConvertable(jsonConverter, reader, contract.DictionaryValueType, null)); dictionary[obj2] = value; } catch (Exception ex2) { if (IsErrorHandled(obj, contract, obj2, reader as IJsonLineInfo, reader.Path, ex2)) { HandleError(reader, readPastError: true, depth); break; } throw; } break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, obj, "Unexpected end when deserializing object."); } OnDeserialized(reader, contract, obj); return obj; } private object PopulateMultidimensionalArray(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty? containerProperty, string? id) { int arrayRank = contract.UnderlyingType.GetArrayRank(); if (id != null) { AddReference(reader, id, list); } OnDeserializing(reader, contract, list); JsonContract contractSafe = GetContractSafe(contract.CollectionItemType); JsonConverter converter = GetConverter(contractSafe, null, contract, containerProperty); int? num = null; Stack stack = new Stack(); stack.Push(list); IList list2 = list; bool flag = false; do { int depth = reader.Depth; if (stack.Count == arrayRank) { try { if (reader.ReadForType(contractSafe, converter != null)) { switch (reader.TokenType) { case JsonToken.EndArray: stack.Pop(); list2 = stack.Peek(); num = null; break; default: { object value = ((converter == null || !converter.CanRead) ? CreateValueInternal(reader, contract.CollectionItemType, contractSafe, null, contract, containerProperty, null) : DeserializeConvertable(converter, reader, contract.CollectionItemType, null)); list2.Add(value); break; } case JsonToken.Comment: break; } continue; } } catch (Exception ex) { JsonPosition position = reader.GetPosition(depth); if (IsErrorHandled(list, contract, position.Position, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, depth + 1); if (num.HasValue && num == position.Position) { throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex); } num = position.Position; continue; } throw; } break; } if (!reader.Read()) { break; } switch (reader.TokenType) { case JsonToken.StartArray: { IList list3 = new List(); list2.Add(list3); stack.Push(list3); list2 = list3; break; } case JsonToken.EndArray: stack.Pop(); if (stack.Count > 0) { list2 = stack.Peek(); } else { flag = true; } break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing multidimensional array: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag); if (!flag) { ThrowUnexpectedEndException(reader, contract, list, "Unexpected end when deserializing array."); } OnDeserialized(reader, contract, list); return list; } private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contract, object? currentObject, string message) { try { throw JsonSerializationException.Create(reader, message); } catch (Exception ex) { if (IsErrorHandled(currentObject, contract, null, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: false, 0); return; } throw; } } private object PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty? containerProperty, string? id) { object obj = ((list is IWrappedCollection wrappedCollection) ? wrappedCollection.UnderlyingCollection : list); if (id != null) { AddReference(reader, id, obj); } if (list.IsFixedSize) { reader.Skip(); return obj; } OnDeserializing(reader, contract, obj); int depth = reader.Depth; if (contract.ItemContract == null) { contract.ItemContract = GetContractSafe(contract.CollectionItemType); } JsonConverter converter = GetConverter(contract.ItemContract, null, contract, containerProperty); int? num = null; bool flag = false; do { try { if (reader.ReadForType(contract.ItemContract, converter != null)) { switch (reader.TokenType) { case JsonToken.EndArray: flag = true; break; default: { object value = ((converter == null || !converter.CanRead) ? CreateValueInternal(reader, contract.CollectionItemType, contract.ItemContract, null, contract, containerProperty, null) : DeserializeConvertable(converter, reader, contract.CollectionItemType, null)); list.Add(value); break; } case JsonToken.Comment: break; } continue; } } catch (Exception ex) { JsonPosition position = reader.GetPosition(depth); if (IsErrorHandled(obj, contract, position.Position, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, depth + 1); if (num.HasValue && num == position.Position) { throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex); } num = position.Position; continue; } throw; } break; } while (!flag); if (!flag) { ThrowUnexpectedEndException(reader, contract, obj, "Unexpected end when deserializing array."); } OnDeserialized(reader, contract, obj); return obj; } private object CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty? member, string? id) { Type underlyingType = contract.UnderlyingType; if (!JsonTypeReflector.FullyTrusted) { string format = "Type '{0}' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine + "To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine; format = format.FormatWith(CultureInfo.InvariantCulture, underlyingType); throw JsonSerializationException.Create(reader, format); } if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using ISerializable constructor.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new JsonFormatterConverter(this, contract, member)); bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } serializationInfo.AddValue(text, JToken.ReadFrom(reader)); break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, serializationInfo, "Unexpected end when deserializing object."); } if (!contract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.ISerializableCreator == null) { throw JsonSerializationException.Create(reader, "ISerializable type '{0}' does not have a valid constructor. To correctly implement ISerializable a constructor that takes SerializationInfo and StreamingContext parameters should be present.".FormatWith(CultureInfo.InvariantCulture, underlyingType)); } object obj = contract.ISerializableCreator(serializationInfo, Serializer._context); if (id != null) { AddReference(reader, id, obj); } OnDeserializing(reader, contract, obj); OnDeserialized(reader, contract, obj); return obj; } internal object? CreateISerializableItem(JToken token, Type type, JsonISerializableContract contract, JsonProperty? member) { JsonContract contractSafe = GetContractSafe(type); JsonConverter converter = GetConverter(contractSafe, null, contract, member); JsonReader jsonReader = token.CreateReader(); jsonReader.MaxDepth = Serializer.MaxDepth; jsonReader.ReadAndAssert(); if (converter != null && converter.CanRead) { return DeserializeConvertable(converter, jsonReader, type, null); } return CreateValueInternal(jsonReader, type, contractSafe, null, contract, member, null); } private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty? member, string? id) { if (!contract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor)) { IDynamicMetaObjectProvider dynamicMetaObjectProvider = (IDynamicMetaObjectProvider)contract.DefaultCreator(); if (id != null) { AddReference(reader, id, dynamicMetaObjectProvider); } OnDeserializing(reader, contract, dynamicMetaObjectProvider); int depth = reader.Depth; bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); try { if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } JsonProperty closestMatchProperty = contract.Properties.GetClosestMatchProperty(text); if (closestMatchProperty != null && closestMatchProperty.Writable && !closestMatchProperty.Ignored) { if (closestMatchProperty.PropertyContract == null) { closestMatchProperty.PropertyContract = GetContractSafe(closestMatchProperty.PropertyType); } JsonConverter converter = GetConverter(closestMatchProperty.PropertyContract, closestMatchProperty.Converter, null, null); if (!SetPropertyValue(closestMatchProperty, converter, null, member, reader, dynamicMetaObjectProvider)) { reader.Skip(); } } else { Type type = (JsonTokenUtils.IsPrimitiveToken(reader.TokenType) ? reader.ValueType : typeof(IDynamicMetaObjectProvider)); JsonContract contractSafe = GetContractSafe(type); JsonConverter converter2 = GetConverter(contractSafe, null, null, member); object value = ((converter2 == null || !converter2.CanRead) ? CreateValueInternal(reader, type, contractSafe, null, null, member, null) : DeserializeConvertable(converter2, reader, type, null)); contract.TrySetMember(dynamicMetaObjectProvider, text, value); } } catch (Exception ex) { if (IsErrorHandled(dynamicMetaObjectProvider, contract, text, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, depth); break; } throw; } break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, dynamicMetaObjectProvider, "Unexpected end when deserializing object."); } OnDeserialized(reader, contract, dynamicMetaObjectProvider); return dynamicMetaObjectProvider; } throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)); } private object CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty? containerProperty, ObjectConstructor creator, string? id) { ValidationUtils.ArgumentNotNull(creator, "creator"); bool flag = contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate); Type underlyingType = contract.UnderlyingType; if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { string arg = string.Join(", ", contract.CreatorParameters.Select((JsonProperty p) => p.PropertyName)); TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using creator with parameters: {1}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, arg)), null); } List list = ResolvePropertyAndCreatorValues(contract, containerProperty, reader, underlyingType); if (flag) { foreach (JsonProperty property in contract.Properties) { if (!property.Ignored && list.All((CreatorPropertyContext p) => p.Property != property)) { list.Add(new CreatorPropertyContext(property.PropertyName) { Property = property, Presence = PropertyPresence.None }); } } } object[] array = new object[contract.CreatorParameters.Count]; foreach (CreatorPropertyContext item in list) { if (flag && item.Property != null && !item.Presence.HasValue) { object value = item.Value; PropertyPresence value2 = ((value == null) ? PropertyPresence.Null : ((!(value is string s)) ? PropertyPresence.Value : (CoerceEmptyStringToNull(item.Property.PropertyType, item.Property.PropertyContract, s) ? PropertyPresence.Null : PropertyPresence.Value))); item.Presence = value2; } JsonProperty jsonProperty = item.ConstructorProperty; if (jsonProperty == null && item.Property != null) { jsonProperty = contract.CreatorParameters.ForgivingCaseSensitiveFind((JsonProperty p) => p.PropertyName, item.Property.UnderlyingName); } if (jsonProperty == null || jsonProperty.Ignored) { continue; } if (flag && (item.Presence == PropertyPresence.None || item.Presence == PropertyPresence.Null)) { if (jsonProperty.PropertyContract == null) { jsonProperty.PropertyContract = GetContractSafe(jsonProperty.PropertyType); } if (HasFlag(jsonProperty.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate)) { item.Value = EnsureType(reader, jsonProperty.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, jsonProperty.PropertyContract, jsonProperty.PropertyType); } } int num = contract.CreatorParameters.IndexOf(jsonProperty); array[num] = item.Value; item.Used = true; } object obj = creator(array); if (id != null) { AddReference(reader, id, obj); } OnDeserializing(reader, contract, obj); foreach (CreatorPropertyContext item2 in list) { if (item2.Used || item2.Property == null || item2.Property.Ignored || item2.Presence == PropertyPresence.None) { continue; } JsonProperty property2 = item2.Property; object value3 = item2.Value; if (ShouldSetPropertyValue(property2, contract, value3)) { property2.ValueProvider.SetValue(obj, value3); item2.Used = true; } else { if (property2.Writable || value3 == null) { continue; } JsonContract jsonContract = Serializer._contractResolver.ResolveContract(property2.PropertyType); if (jsonContract.ContractType == JsonContractType.Array) { JsonArrayContract jsonArrayContract = (JsonArrayContract)jsonContract; if (jsonArrayContract.CanDeserialize && !jsonArrayContract.IsReadOnlyOrFixedSize) { object value4 = property2.ValueProvider.GetValue(obj); if (value4 != null) { jsonArrayContract = (JsonArrayContract)GetContract(value4.GetType()); object obj2; if (!jsonArrayContract.ShouldCreateWrapper) { obj2 = (IList)value4; } else { IList list2 = jsonArrayContract.CreateWrapper(value4); obj2 = list2; } IList list3 = (IList)obj2; if (!list3.IsFixedSize) { object obj3; if (!jsonArrayContract.ShouldCreateWrapper) { obj3 = (IList)value3; } else { IList list2 = jsonArrayContract.CreateWrapper(value3); obj3 = list2; } foreach (object item3 in (IEnumerable)obj3) { list3.Add(item3); } } } } } else if (jsonContract.ContractType == JsonContractType.Dictionary) { JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)jsonContract; if (!jsonDictionaryContract.IsReadOnlyOrFixedSize) { object value5 = property2.ValueProvider.GetValue(obj); if (value5 != null) { object obj4; if (!jsonDictionaryContract.ShouldCreateWrapper) { obj4 = (IDictionary)value5; } else { IDictionary dictionary = jsonDictionaryContract.CreateWrapper(value5); obj4 = dictionary; } IDictionary dictionary2 = (IDictionary)obj4; object obj5; if (!jsonDictionaryContract.ShouldCreateWrapper) { obj5 = (IDictionary)value3; } else { IDictionary dictionary = jsonDictionaryContract.CreateWrapper(value3); obj5 = dictionary; } foreach (DictionaryEntry item4 in (IDictionary)obj5) { dictionary2[item4.Key] = item4.Value; } } } } item2.Used = true; } } if (contract.ExtensionDataSetter != null) { foreach (CreatorPropertyContext item5 in list) { if (!item5.Used && item5.Presence != PropertyPresence.None) { contract.ExtensionDataSetter(obj, item5.Name, item5.Value); } } } if (flag) { foreach (CreatorPropertyContext item6 in list) { if (item6.Property != null) { EndProcessProperty(obj, reader, contract, reader.Depth, item6.Property, item6.Presence.GetValueOrDefault(), !item6.Used); } } } OnDeserialized(reader, contract, obj); return obj; } private object? DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object? existingValue) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), null); } object? result = converter.ReadJson(reader, objectType, existingValue, GetInternalSerializer()); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Finished deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), null); } return result; } private List ResolvePropertyAndCreatorValues(JsonObjectContract contract, JsonProperty? containerProperty, JsonReader reader, Type objectType) { List list = new List(); bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); CreatorPropertyContext creatorPropertyContext = new CreatorPropertyContext(text) { ConstructorProperty = contract.CreatorParameters.GetClosestMatchProperty(text), Property = contract.Properties.GetClosestMatchProperty(text) }; list.Add(creatorPropertyContext); JsonProperty jsonProperty = creatorPropertyContext.ConstructorProperty ?? creatorPropertyContext.Property; if (jsonProperty != null) { if (!jsonProperty.Ignored) { if (jsonProperty.PropertyContract == null) { jsonProperty.PropertyContract = GetContractSafe(jsonProperty.PropertyType); } JsonConverter converter = GetConverter(jsonProperty.PropertyContract, jsonProperty.Converter, contract, containerProperty); if (!reader.ReadForType(jsonProperty.PropertyContract, converter != null)) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } if (converter != null && converter.CanRead) { creatorPropertyContext.Value = DeserializeConvertable(converter, reader, jsonProperty.PropertyType, null); } else { creatorPropertyContext.Value = CreateValueInternal(reader, jsonProperty.PropertyType, jsonProperty.PropertyContract, jsonProperty, contract, containerProperty, null); } break; } if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } } else { if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, text, contract.UnderlyingType)), null); } if ((contract.MissingMemberHandling ?? Serializer._missingMemberHandling) == MissingMemberHandling.Error) { throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, text, objectType.Name)); } } if (contract.ExtensionDataSetter != null) { creatorPropertyContext.Value = ReadExtensionDataValue(contract, containerProperty, reader); } else { reader.Skip(); } break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, null, "Unexpected end when deserializing object."); } return list; } public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty? containerMember, JsonProperty? containerProperty, string? id, out bool createdFromNonDefaultCreator) { object obj = null; if (objectContract.OverrideCreator != null) { if (objectContract.CreatorParameters.Count > 0) { createdFromNonDefaultCreator = true; return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.OverrideCreator, id); } obj = objectContract.OverrideCreator(CollectionUtils.ArrayEmpty()); } else if (objectContract.DefaultCreator != null && (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParameterizedCreator == null)) { obj = objectContract.DefaultCreator(); } else if (objectContract.ParameterizedCreator != null) { createdFromNonDefaultCreator = true; return CreateObjectUsingCreatorWithParameters(reader, objectContract, containerMember, objectContract.ParameterizedCreator, id); } if (obj == null) { if (!objectContract.IsInstantiable) { throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType)); } throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType)); } createdFromNonDefaultCreator = false; return obj; } private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty? member, string? id) { OnDeserializing(reader, contract, newObject); Dictionary dictionary = ((contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate)) ? contract.Properties.ToDictionary((JsonProperty m) => m, (JsonProperty m) => PropertyPresence.None) : null); if (id != null) { AddReference(reader, id, newObject); } int depth = reader.Depth; bool flag = false; do { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); if (CheckPropertyName(reader, text)) { break; } try { JsonProperty closestMatchProperty = contract.Properties.GetClosestMatchProperty(text); if (closestMatchProperty == null) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}".FormatWith(CultureInfo.InvariantCulture, text, contract.UnderlyingType)), null); } if ((contract.MissingMemberHandling ?? Serializer._missingMemberHandling) == MissingMemberHandling.Error) { throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, text, contract.UnderlyingType.Name)); } if (reader.Read()) { SetExtensionData(contract, member, reader, text, newObject); } break; } if (closestMatchProperty.Ignored || !ShouldDeserialize(reader, closestMatchProperty, newObject)) { if (reader.Read()) { SetPropertyPresence(reader, closestMatchProperty, dictionary); SetExtensionData(contract, member, reader, text, newObject); } break; } if (closestMatchProperty.PropertyContract == null) { closestMatchProperty.PropertyContract = GetContractSafe(closestMatchProperty.PropertyType); } JsonConverter converter = GetConverter(closestMatchProperty.PropertyContract, closestMatchProperty.Converter, contract, member); if (!reader.ReadForType(closestMatchProperty.PropertyContract, converter != null)) { throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, text)); } SetPropertyPresence(reader, closestMatchProperty, dictionary); if (!SetPropertyValue(closestMatchProperty, converter, contract, member, reader, newObject)) { SetExtensionData(contract, member, reader, text, newObject); } } catch (Exception ex) { if (IsErrorHandled(newObject, contract, text, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, depth); break; } throw; } break; } case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType); case JsonToken.Comment: break; } } while (!flag && reader.Read()); if (!flag) { ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object."); } if (dictionary != null) { foreach (KeyValuePair item in dictionary) { JsonProperty key = item.Key; PropertyPresence value = item.Value; EndProcessProperty(newObject, reader, contract, depth, key, value, setDefaultValue: true); } } OnDeserialized(reader, contract, newObject); return newObject; } private bool ShouldDeserialize(JsonReader reader, JsonProperty property, object target) { if (property.ShouldDeserialize == null) { return true; } bool flag = property.ShouldDeserialize(target); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, reader.Path, "ShouldDeserialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, flag)), null); } return flag; } private bool CheckPropertyName(JsonReader reader, string memberName) { if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead) { switch (memberName) { case "$id": case "$ref": case "$type": case "$values": reader.Skip(); return true; } } return false; } private void SetExtensionData(JsonObjectContract contract, JsonProperty? member, JsonReader reader, string memberName, object o) { if (contract.ExtensionDataSetter != null) { try { object value = ReadExtensionDataValue(contract, member, reader); contract.ExtensionDataSetter(o, memberName, value); return; } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error setting value in extension data for type '{0}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType), ex); } } reader.Skip(); } private object? ReadExtensionDataValue(JsonObjectContract contract, JsonProperty? member, JsonReader reader) { if (contract.ExtensionDataIsJToken) { return JToken.ReadFrom(reader); } return CreateValueInternal(reader, null, null, null, contract, member, null); } private void EndProcessProperty(object newObject, JsonReader reader, JsonObjectContract contract, int initialDepth, JsonProperty property, PropertyPresence presence, bool setDefaultValue) { if (presence != 0 && presence != PropertyPresence.Null) { return; } try { Required required = ((!property.Ignored) ? (property._required ?? contract.ItemRequired.GetValueOrDefault()) : Required.Default); switch (presence) { case PropertyPresence.None: if (required == Required.AllowNull || required == Required.Always) { throw JsonSerializationException.Create(reader, "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName)); } if (setDefaultValue && !property.Ignored) { if (property.PropertyContract == null) { property.PropertyContract = GetContractSafe(property.PropertyType); } if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && property.Writable) { property.ValueProvider.SetValue(newObject, EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType)); } } break; case PropertyPresence.Null: switch (required) { case Required.Always: throw JsonSerializationException.Create(reader, "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName)); case Required.DisallowNull: throw JsonSerializationException.Create(reader, "Required property '{0}' expects a non-null value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName)); } break; } } catch (Exception ex) { if (IsErrorHandled(newObject, contract, property.PropertyName, reader as IJsonLineInfo, reader.Path, ex)) { HandleError(reader, readPastError: true, initialDepth); return; } throw; } } private void SetPropertyPresence(JsonReader reader, JsonProperty property, Dictionary? requiredProperties) { if (property != null && requiredProperties != null) { PropertyPresence value; switch (reader.TokenType) { case JsonToken.String: value = (CoerceEmptyStringToNull(property.PropertyType, property.PropertyContract, (string)reader.Value) ? PropertyPresence.Null : PropertyPresence.Value); break; case JsonToken.Null: case JsonToken.Undefined: value = PropertyPresence.Null; break; default: value = PropertyPresence.Value; break; } requiredProperties[property] = value; } } private void HandleError(JsonReader reader, bool readPastError, int initialDepth) { ClearErrorContext(); if (readPastError) { reader.Skip(); while (reader.Depth > initialDepth && reader.Read()) { } } } } internal class JsonSerializerInternalWriter : JsonSerializerInternalBase { private Type? _rootType; private int _rootLevel; private readonly List _serializeStack = new List(); public JsonSerializerInternalWriter(JsonSerializer serializer) : base(serializer) { } public void Serialize(JsonWriter jsonWriter, object? value, Type? objectType) { if (jsonWriter == null) { throw new ArgumentNullException("jsonWriter"); } _rootType = objectType; _rootLevel = _serializeStack.Count + 1; JsonContract contractSafe = GetContractSafe(value); try { if (ShouldWriteReference(value, null, contractSafe, null, null)) { WriteReference(jsonWriter, value); } else { SerializeValue(jsonWriter, value, contractSafe, null, null, null); } } catch (Exception ex) { if (IsErrorHandled(null, contractSafe, null, null, jsonWriter.Path, ex)) { HandleError(jsonWriter, 0); return; } ClearErrorContext(); throw; } finally { _rootType = null; } } private JsonSerializerProxy GetInternalSerializer() { if (InternalSerializer == null) { InternalSerializer = new JsonSerializerProxy(this); } return InternalSerializer; } private JsonContract? GetContractSafe(object? value) { if (value == null) { return null; } return GetContract(value); } private JsonContract GetContract(object value) { return Serializer._contractResolver.ResolveContract(value.GetType()); } private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { if (contract.TypeCode == PrimitiveTypeCode.Bytes && ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty)) { writer.WriteStartObject(); WriteTypeProperty(writer, contract.CreatedType); writer.WritePropertyName("$value", escape: false); JsonWriter.WriteValue(writer, contract.TypeCode, value); writer.WriteEndObject(); } else { JsonWriter.WriteValue(writer, contract.TypeCode, value); } } private void SerializeValue(JsonWriter writer, object? value, JsonContract? valueContract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { if (value == null) { writer.WriteNull(); return; } JsonConverter jsonConverter = member?.Converter ?? containerProperty?.ItemConverter ?? containerContract?.ItemConverter ?? valueContract.Converter ?? Serializer.GetMatchingConverter(valueContract.UnderlyingType) ?? valueContract.InternalConverter; if (jsonConverter != null && jsonConverter.CanWrite) { SerializeConvertable(writer, jsonConverter, value, valueContract, containerContract, containerProperty); return; } switch (valueContract.ContractType) { case JsonContractType.Object: SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.Array: { JsonArrayContract jsonArrayContract = (JsonArrayContract)valueContract; if (!jsonArrayContract.IsMultidimensionalArray) { SerializeList(writer, (IEnumerable)value, jsonArrayContract, member, containerContract, containerProperty); } else { SerializeMultidimensionalArray(writer, (Array)value, jsonArrayContract, member, containerContract, containerProperty); } break; } case JsonContractType.Primitive: SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.String: SerializeString(writer, value, (JsonStringContract)valueContract); break; case JsonContractType.Dictionary: { JsonDictionaryContract jsonDictionaryContract = (JsonDictionaryContract)valueContract; IDictionary values; if (!(value is IDictionary dictionary)) { IDictionary dictionary2 = jsonDictionaryContract.CreateWrapper(value); values = dictionary2; } else { values = dictionary; } SerializeDictionary(writer, values, jsonDictionaryContract, member, containerContract, containerProperty); break; } case JsonContractType.Dynamic: SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.Serializable: SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty); break; case JsonContractType.Linq: ((JToken)value).WriteTo(writer, Serializer.Converters.ToArray()); break; } } private bool? ResolveIsReference(JsonContract contract, JsonProperty? property, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { bool? result = null; if (property != null) { result = property.IsReference; } if (!result.HasValue && containerProperty != null) { result = containerProperty.ItemIsReference; } if (!result.HasValue && collectionContract != null) { result = collectionContract.ItemIsReference; } if (!result.HasValue) { result = contract.IsReference; } return result; } private bool ShouldWriteReference(object? value, JsonProperty? property, JsonContract? valueContract, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { if (value == null) { return false; } if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String) { return false; } bool? flag = ResolveIsReference(valueContract, property, collectionContract, containerProperty); if (!flag.HasValue) { flag = ((valueContract.ContractType != JsonContractType.Array) ? new bool?(HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects)) : new bool?(HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays))); } if (!flag.GetValueOrDefault()) { return false; } return Serializer.GetReferenceResolver().IsReferenced(this, value); } private bool ShouldWriteProperty(object? memberValue, JsonObjectContract? containerContract, JsonProperty property) { if (memberValue == null && ResolvedNullValueHandling(containerContract, property) == NullValueHandling.Ignore) { return false; } if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore) && MiscellaneousUtils.ValueEquals(memberValue, property.GetResolvedDefaultValue())) { return false; } return true; } private bool CheckForCircularReference(JsonWriter writer, object? value, JsonProperty? property, JsonContract? contract, JsonContainerContract? containerContract, JsonProperty? containerProperty) { if (value == null) { return true; } if (contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String) { return true; } ReferenceLoopHandling? referenceLoopHandling = null; if (property != null) { referenceLoopHandling = property.ReferenceLoopHandling; } if (!referenceLoopHandling.HasValue && containerProperty != null) { referenceLoopHandling = containerProperty.ItemReferenceLoopHandling; } if (!referenceLoopHandling.HasValue && containerContract != null) { referenceLoopHandling = containerContract.ItemReferenceLoopHandling; } if ((Serializer._equalityComparer != null) ? _serializeStack.Contains(value, Serializer._equalityComparer) : _serializeStack.Contains(value)) { string text = "Self referencing loop detected"; if (property != null) { text += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName); } text += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()); switch (referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling)) { case ReferenceLoopHandling.Error: throw JsonSerializationException.Create(null, writer.ContainerPath, text, null); case ReferenceLoopHandling.Ignore: if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, text + ". Skipping serializing self referenced value."), null); } return false; case ReferenceLoopHandling.Serialize: if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, text + ". Serializing self referenced value."), null); } return true; } } return true; } private void WriteReference(JsonWriter writer, object value) { string reference = GetReference(writer, value); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference to Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, value.GetType())), null); } writer.WriteStartObject(); writer.WritePropertyName("$ref", escape: false); writer.WriteValue(reference); writer.WriteEndObject(); } private string GetReference(JsonWriter writer, object value) { try { return Serializer.GetReferenceResolver().GetReference(this, value); } catch (Exception ex) { throw JsonSerializationException.Create(null, writer.ContainerPath, "Error writing object reference for '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), ex); } } internal static bool TryConvertToString(object value, Type type, [NotNullWhen(true)] out string? s) { if (JsonTypeReflector.CanTypeDescriptorConvertString(type, out TypeConverter typeConverter)) { s = typeConverter.ConvertToInvariantString(value); return true; } if (value is Type type2) { s = type2.AssemblyQualifiedName; return true; } s = null; return false; } private void SerializeString(JsonWriter writer, object value, JsonStringContract contract) { OnSerializing(writer, contract, value); TryConvertToString(value, contract.UnderlyingType, out string s); writer.WriteValue(s); OnSerialized(writer, contract, value); } private void OnSerializing(JsonWriter writer, JsonContract contract, object value) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } contract.InvokeOnSerializing(value, Serializer._context); } private void OnSerialized(JsonWriter writer, JsonContract contract, object value) { if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null); } contract.InvokeOnSerialized(value, Serializer._context); } private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { OnSerializing(writer, contract, value); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); int top = writer.Top; for (int i = 0; i < contract.Properties.Count; i++) { JsonProperty jsonProperty = contract.Properties[i]; try { if (CalculatePropertyValues(writer, value, contract, member, jsonProperty, out JsonContract memberContract, out object memberValue)) { jsonProperty.WritePropertyName(writer); SerializeValue(writer, memberValue, memberContract, jsonProperty, contract, member); } } catch (Exception ex) { if (IsErrorHandled(value, contract, jsonProperty.PropertyName, null, writer.ContainerPath, ex)) { HandleError(writer, top); continue; } throw; } } IEnumerable> enumerable = contract.ExtensionDataGetter?.Invoke(value); if (enumerable != null) { foreach (KeyValuePair item in enumerable) { JsonContract contract2 = GetContract(item.Key); JsonContract contractSafe = GetContractSafe(item.Value); string propertyName = GetPropertyName(writer, item.Key, contract2, out var _); propertyName = ((contract.ExtensionDataNameResolver != null) ? contract.ExtensionDataNameResolver(propertyName) : propertyName); if (ShouldWriteReference(item.Value, null, contractSafe, contract, member)) { writer.WritePropertyName(propertyName); WriteReference(writer, item.Value); } else if (CheckForCircularReference(writer, item.Value, null, contractSafe, contract, member)) { writer.WritePropertyName(propertyName); SerializeValue(writer, item.Value, contractSafe, null, contract, member); } } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); } private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty? member, JsonProperty property, [NotNullWhen(true)] out JsonContract? memberContract, out object? memberValue) { if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value)) { if (property.PropertyContract == null) { property.PropertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType); } memberValue = property.ValueProvider.GetValue(value); memberContract = (property.PropertyContract.IsSealed ? property.PropertyContract : GetContractSafe(memberValue)); if (ShouldWriteProperty(memberValue, contract as JsonObjectContract, property)) { if (ShouldWriteReference(memberValue, property, memberContract, contract, member)) { property.WritePropertyName(writer); WriteReference(writer, memberValue); return false; } if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member)) { return false; } if (memberValue == null) { JsonObjectContract jsonObjectContract = contract as JsonObjectContract; switch (property._required ?? (jsonObjectContract?.ItemRequired).GetValueOrDefault()) { case Required.Always: throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null); case Required.DisallowNull: throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a non-null value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null); } } return true; } } memberContract = null; memberValue = null; return false; } private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { writer.WriteStartObject(); if ((ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects)) && (member == null || member.Writable || HasCreatorParameter(collectionContract, member))) { WriteReferenceIdProperty(writer, contract.UnderlyingType, value); } if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty)) { WriteTypeProperty(writer, contract.UnderlyingType); } } private bool HasCreatorParameter(JsonContainerContract? contract, JsonProperty property) { if (!(contract is JsonObjectContract jsonObjectContract)) { return false; } return jsonObjectContract.CreatorParameters.Contains(property.PropertyName); } private void WriteReferenceIdProperty(JsonWriter writer, Type type, object value) { string reference = GetReference(writer, value); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, type)), null); } writer.WritePropertyName("$id", escape: false); writer.WriteValue(reference); } private void WriteTypeProperty(JsonWriter writer, Type type) { string typeName = ReflectionUtils.GetTypeName(type, Serializer._typeNameAssemblyFormatHandling, Serializer._serializationBinder); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing type name '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, typeName, type)), null); } writer.WritePropertyName("$type", escape: false); writer.WriteValue(typeName); } private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) { return (value & flag) == flag; } private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag) { return (value & flag) == flag; } private bool HasFlag(TypeNameHandling value, TypeNameHandling flag) { return (value & flag) == flag; } private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty)) { WriteReference(writer, value); } else if (CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty)) { _serializeStack.Add(value); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null); } converter.WriteJson(writer, value, GetInternalSerializer()); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info) { TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null); } _serializeStack.RemoveAt(_serializeStack.Count - 1); } } private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { object obj = ((values is IWrappedCollection wrappedCollection) ? wrappedCollection.UnderlyingCollection : values); OnSerializing(writer, contract, obj); _serializeStack.Add(obj); bool flag = WriteStartArray(writer, obj, contract, member, collectionContract, containerProperty); writer.WriteStartArray(); int top = writer.Top; int num = 0; foreach (object value in values) { try { JsonContract jsonContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, jsonContract, contract, member)) { WriteReference(writer, value); } else if (CheckForCircularReference(writer, value, null, jsonContract, contract, member)) { SerializeValue(writer, value, jsonContract, null, contract, member); } } catch (Exception ex) { if (IsErrorHandled(obj, contract, num, null, writer.ContainerPath, ex)) { HandleError(writer, top); continue; } throw; } finally { num++; } } writer.WriteEndArray(); if (flag) { writer.WriteEndObject(); } _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, obj); } private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { OnSerializing(writer, contract, values); _serializeStack.Add(values); bool num = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty); SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, CollectionUtils.ArrayEmpty()); if (num) { writer.WriteEndObject(); } _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, values); } private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty? member, int initialDepth, int[] indices) { int num = indices.Length; int[] array = new int[num + 1]; for (int i = 0; i < num; i++) { array[i] = indices[i]; } writer.WriteStartArray(); for (int j = values.GetLowerBound(num); j <= values.GetUpperBound(num); j++) { array[num] = j; if (array.Length == values.Rank) { object value = values.GetValue(array); try { JsonContract jsonContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, jsonContract, contract, member)) { WriteReference(writer, value); } else if (CheckForCircularReference(writer, value, null, jsonContract, contract, member)) { SerializeValue(writer, value, jsonContract, null, contract, member); } } catch (Exception ex) { if (IsErrorHandled(values, contract, j, null, writer.ContainerPath, ex)) { HandleError(writer, initialDepth + 1); continue; } throw; } } else { SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, array); } } writer.WriteEndArray(); } private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { bool flag = (ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays)) && (member == null || member.Writable || HasCreatorParameter(containerContract, member)); bool flag2 = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty); bool num = flag || flag2; if (num) { writer.WriteStartObject(); if (flag) { WriteReferenceIdProperty(writer, contract.UnderlyingType, values); } if (flag2) { WriteTypeProperty(writer, values.GetType()); } writer.WritePropertyName("$values", escape: false); } if (contract.ItemContract == null) { contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object)); } return num; } [SecuritySafeCritical] private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { if (!JsonTypeReflector.FullyTrusted) { string format = "Type '{0}' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data." + Environment.NewLine + "To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true." + Environment.NewLine; format = format.FormatWith(CultureInfo.InvariantCulture, value.GetType()); throw JsonSerializationException.Create(null, writer.ContainerPath, format, null); } OnSerializing(writer, contract, value); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter()); value.GetObjectData(serializationInfo, Serializer._context); SerializationInfoEnumerator enumerator = serializationInfo.GetEnumerator(); while (enumerator.MoveNext()) { SerializationEntry current = enumerator.Current; JsonContract contractSafe = GetContractSafe(current.Value); if (ShouldWriteReference(current.Value, null, contractSafe, contract, member)) { writer.WritePropertyName(current.Name); WriteReference(writer, current.Value); } else if (CheckForCircularReference(writer, current.Value, null, contractSafe, contract, member)) { writer.WritePropertyName(current.Name); SerializeValue(writer, current.Value, contractSafe, null, contract, member); } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); } private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { OnSerializing(writer, contract, value); _serializeStack.Add(value); WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty); int top = writer.Top; for (int i = 0; i < contract.Properties.Count; i++) { JsonProperty jsonProperty = contract.Properties[i]; if (!jsonProperty.HasMemberAttribute) { continue; } try { if (CalculatePropertyValues(writer, value, contract, member, jsonProperty, out JsonContract memberContract, out object memberValue)) { jsonProperty.WritePropertyName(writer); SerializeValue(writer, memberValue, memberContract, jsonProperty, contract, member); } } catch (Exception ex) { if (IsErrorHandled(value, contract, jsonProperty.PropertyName, null, writer.ContainerPath, ex)) { HandleError(writer, top); continue; } throw; } } foreach (string dynamicMemberName in value.GetDynamicMemberNames()) { if (!contract.TryGetMember(value, dynamicMemberName, out object value2)) { continue; } try { JsonContract contractSafe = GetContractSafe(value2); if (ShouldWriteDynamicProperty(value2) && CheckForCircularReference(writer, value2, null, contractSafe, contract, member)) { string name = ((contract.PropertyNameResolver != null) ? contract.PropertyNameResolver(dynamicMemberName) : dynamicMemberName); writer.WritePropertyName(name); SerializeValue(writer, value2, contractSafe, null, contract, member); } } catch (Exception ex2) { if (IsErrorHandled(value, contract, dynamicMemberName, null, writer.ContainerPath, ex2)) { HandleError(writer, top); continue; } throw; } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, value); } private bool ShouldWriteDynamicProperty(object? memberValue) { if (Serializer._nullValueHandling == NullValueHandling.Ignore && memberValue == null) { return false; } if (HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Ignore) && (memberValue == null || MiscellaneousUtils.ValueEquals(memberValue, ReflectionUtils.GetDefaultValue(memberValue.GetType())))) { return false; } return true; } private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty? member, JsonContainerContract? containerContract, JsonProperty? containerProperty) { TypeNameHandling value = member?.TypeNameHandling ?? containerProperty?.ItemTypeNameHandling ?? containerContract?.ItemTypeNameHandling ?? Serializer._typeNameHandling; if (HasFlag(value, typeNameHandlingFlag)) { return true; } if (HasFlag(value, TypeNameHandling.Auto)) { if (member != null) { if (contract.NonNullableUnderlyingType != member.PropertyContract.CreatedType) { return true; } } else if (containerContract != null) { if (containerContract.ItemContract == null || contract.NonNullableUnderlyingType != containerContract.ItemContract.CreatedType) { return true; } } else if (_rootType != null && _serializeStack.Count == _rootLevel) { JsonContract jsonContract = Serializer._contractResolver.ResolveContract(_rootType); if (contract.NonNullableUnderlyingType != jsonContract.CreatedType) { return true; } } } return false; } private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty? member, JsonContainerContract? collectionContract, JsonProperty? containerProperty) { object obj = ((values is IWrappedDictionary wrappedDictionary) ? wrappedDictionary.UnderlyingDictionary : values); OnSerializing(writer, contract, obj); _serializeStack.Add(obj); WriteObjectStart(writer, obj, contract, member, collectionContract, containerProperty); if (contract.ItemContract == null) { contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object)); } if (contract.KeyContract == null) { contract.KeyContract = Serializer._contractResolver.ResolveContract(contract.DictionaryKeyType ?? typeof(object)); } int top = writer.Top; foreach (DictionaryEntry value2 in values) { string propertyName = GetPropertyName(writer, value2.Key, contract.KeyContract, out var escape); propertyName = ((contract.DictionaryKeyResolver != null) ? contract.DictionaryKeyResolver(propertyName) : propertyName); try { object value = value2.Value; JsonContract jsonContract = contract.FinalItemContract ?? GetContractSafe(value); if (ShouldWriteReference(value, null, jsonContract, contract, member)) { writer.WritePropertyName(propertyName, escape); WriteReference(writer, value); } else if (CheckForCircularReference(writer, value, null, jsonContract, contract, member)) { writer.WritePropertyName(propertyName, escape); SerializeValue(writer, value, jsonContract, null, contract, member); } } catch (Exception ex) { if (IsErrorHandled(obj, contract, propertyName, null, writer.ContainerPath, ex)) { HandleError(writer, top); continue; } throw; } } writer.WriteEndObject(); _serializeStack.RemoveAt(_serializeStack.Count - 1); OnSerialized(writer, contract, obj); } private string GetPropertyName(JsonWriter writer, object name, JsonContract contract, out bool escape) { if (contract.ContractType == JsonContractType.Primitive) { JsonPrimitiveContract jsonPrimitiveContract = (JsonPrimitiveContract)contract; switch (jsonPrimitiveContract.TypeCode) { case PrimitiveTypeCode.DateTime: case PrimitiveTypeCode.DateTimeNullable: { DateTime value = DateTimeUtils.EnsureDateTime((DateTime)name, writer.DateTimeZoneHandling); escape = false; StringWriter stringWriter2 = new StringWriter(CultureInfo.InvariantCulture); DateTimeUtils.WriteDateTimeString(stringWriter2, value, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); return stringWriter2.ToString(); } case PrimitiveTypeCode.DateTimeOffset: case PrimitiveTypeCode.DateTimeOffsetNullable: { escape = false; StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, (DateTimeOffset)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture); return stringWriter.ToString(); } case PrimitiveTypeCode.Double: case PrimitiveTypeCode.DoubleNullable: { double num = (double)name; escape = false; return num.ToString("R", CultureInfo.InvariantCulture); } case PrimitiveTypeCode.Single: case PrimitiveTypeCode.SingleNullable: { float num2 = (float)name; escape = false; return num2.ToString("R", CultureInfo.InvariantCulture); } default: { escape = true; if (jsonPrimitiveContract.IsEnum && EnumUtils.TryToString(jsonPrimitiveContract.NonNullableUnderlyingType, name, null, out string name2)) { return name2; } return Convert.ToString(name, CultureInfo.InvariantCulture); } } } if (TryConvertToString(name, name.GetType(), out string s)) { escape = true; return s; } escape = true; return name.ToString(); } private void HandleError(JsonWriter writer, int initialDepth) { ClearErrorContext(); if (writer.WriteState == WriteState.Property) { writer.WriteNull(); } while (writer.Top > initialDepth) { writer.WriteEnd(); } } private bool ShouldSerialize(JsonWriter writer, JsonProperty property, object target) { if (property.ShouldSerialize == null) { return true; } bool flag = property.ShouldSerialize(target); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "ShouldSerialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, flag)), null); } return flag; } private bool IsSpecified(JsonWriter writer, JsonProperty property, object target) { if (property.GetIsSpecified == null) { return true; } bool flag = property.GetIsSpecified(target); if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) { TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "IsSpecified result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, flag)), null); } return flag; } } internal class JsonSerializerProxy : JsonSerializer { private readonly JsonSerializerInternalReader? _serializerReader; private readonly JsonSerializerInternalWriter? _serializerWriter; internal readonly JsonSerializer _serializer; public override IReferenceResolver? ReferenceResolver { get { return _serializer.ReferenceResolver; } set { _serializer.ReferenceResolver = value; } } public override ITraceWriter? TraceWriter { get { return _serializer.TraceWriter; } set { _serializer.TraceWriter = value; } } public override IEqualityComparer? EqualityComparer { get { return _serializer.EqualityComparer; } set { _serializer.EqualityComparer = value; } } public override JsonConverterCollection Converters => _serializer.Converters; public override DefaultValueHandling DefaultValueHandling { get { return _serializer.DefaultValueHandling; } set { _serializer.DefaultValueHandling = value; } } public override IContractResolver ContractResolver { get { return _serializer.ContractResolver; } set { _serializer.ContractResolver = value; } } public override MissingMemberHandling MissingMemberHandling { get { return _serializer.MissingMemberHandling; } set { _serializer.MissingMemberHandling = value; } } public override NullValueHandling NullValueHandling { get { return _serializer.NullValueHandling; } set { _serializer.NullValueHandling = value; } } public override ObjectCreationHandling ObjectCreationHandling { get { return _serializer.ObjectCreationHandling; } set { _serializer.ObjectCreationHandling = value; } } public override ReferenceLoopHandling ReferenceLoopHandling { get { return _serializer.ReferenceLoopHandling; } set { _serializer.ReferenceLoopHandling = value; } } public override PreserveReferencesHandling PreserveReferencesHandling { get { return _serializer.PreserveReferencesHandling; } set { _serializer.PreserveReferencesHandling = value; } } public override TypeNameHandling TypeNameHandling { get { return _serializer.TypeNameHandling; } set { _serializer.TypeNameHandling = value; } } public override MetadataPropertyHandling MetadataPropertyHandling { get { return _serializer.MetadataPropertyHandling; } set { _serializer.MetadataPropertyHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public override FormatterAssemblyStyle TypeNameAssemblyFormat { get { return _serializer.TypeNameAssemblyFormat; } set { _serializer.TypeNameAssemblyFormat = value; } } public override TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _serializer.TypeNameAssemblyFormatHandling; } set { _serializer.TypeNameAssemblyFormatHandling = value; } } public override ConstructorHandling ConstructorHandling { get { return _serializer.ConstructorHandling; } set { _serializer.ConstructorHandling = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public override SerializationBinder Binder { get { return _serializer.Binder; } set { _serializer.Binder = value; } } public override ISerializationBinder SerializationBinder { get { return _serializer.SerializationBinder; } set { _serializer.SerializationBinder = value; } } public override StreamingContext Context { get { return _serializer.Context; } set { _serializer.Context = value; } } public override Formatting Formatting { get { return _serializer.Formatting; } set { _serializer.Formatting = value; } } public override DateFormatHandling DateFormatHandling { get { return _serializer.DateFormatHandling; } set { _serializer.DateFormatHandling = value; } } public override DateTimeZoneHandling DateTimeZoneHandling { get { return _serializer.DateTimeZoneHandling; } set { _serializer.DateTimeZoneHandling = value; } } public override DateParseHandling DateParseHandling { get { return _serializer.DateParseHandling; } set { _serializer.DateParseHandling = value; } } public override FloatFormatHandling FloatFormatHandling { get { return _serializer.FloatFormatHandling; } set { _serializer.FloatFormatHandling = value; } } public override FloatParseHandling FloatParseHandling { get { return _serializer.FloatParseHandling; } set { _serializer.FloatParseHandling = value; } } public override StringEscapeHandling StringEscapeHandling { get { return _serializer.StringEscapeHandling; } set { _serializer.StringEscapeHandling = value; } } public override string DateFormatString { get { return _serializer.DateFormatString; } set { _serializer.DateFormatString = value; } } public override CultureInfo Culture { get { return _serializer.Culture; } set { _serializer.Culture = value; } } public override int? MaxDepth { get { return _serializer.MaxDepth; } set { _serializer.MaxDepth = value; } } public override bool CheckAdditionalContent { get { return _serializer.CheckAdditionalContent; } set { _serializer.CheckAdditionalContent = value; } } public override event EventHandler? Error { add { _serializer.Error += value; } remove { _serializer.Error -= value; } } internal JsonSerializerInternalBase GetInternalSerializer() { if (_serializerReader != null) { return _serializerReader; } return _serializerWriter; } public JsonSerializerProxy(JsonSerializerInternalReader serializerReader) { ValidationUtils.ArgumentNotNull(serializerReader, "serializerReader"); _serializerReader = serializerReader; _serializer = serializerReader.Serializer; } public JsonSerializerProxy(JsonSerializerInternalWriter serializerWriter) { ValidationUtils.ArgumentNotNull(serializerWriter, "serializerWriter"); _serializerWriter = serializerWriter; _serializer = serializerWriter.Serializer; } internal override object? DeserializeInternal(JsonReader reader, Type? objectType) { if (_serializerReader != null) { return _serializerReader.Deserialize(reader, objectType, checkAdditionalContent: false); } return _serializer.Deserialize(reader, objectType); } internal override void PopulateInternal(JsonReader reader, object target) { if (_serializerReader != null) { _serializerReader.Populate(reader, target); } else { _serializer.Populate(reader, target); } } internal override void SerializeInternal(JsonWriter jsonWriter, object? value, Type? rootType) { if (_serializerWriter != null) { _serializerWriter.Serialize(jsonWriter, value, rootType); } else { _serializer.Serialize(jsonWriter, value); } } } internal class JsonStringContract : JsonPrimitiveContract { public JsonStringContract(Type underlyingType) : base(underlyingType) { ContractType = JsonContractType.String; } } internal static class JsonTypeReflector { private static bool? _dynamicCodeGeneration; private static bool? _fullyTrusted; public const string IdPropertyName = "$id"; public const string RefPropertyName = "$ref"; public const string TypePropertyName = "$type"; public const string ValuePropertyName = "$value"; public const string ArrayValuesPropertyName = "$values"; public const string ShouldSerializePrefix = "ShouldSerialize"; public const string SpecifiedPostfix = "Specified"; public const string ConcurrentDictionaryTypeName = "System.Collections.Concurrent.ConcurrentDictionary`2"; private static readonly ThreadSafeStore> CreatorCache = new ThreadSafeStore>(GetCreator); private static readonly ThreadSafeStore AssociatedMetadataTypesCache = new ThreadSafeStore(GetAssociateMetadataTypeFromAttribute); private static ReflectionObject? _metadataTypeAttributeReflectionObject; public static bool DynamicCodeGeneration { [SecuritySafeCritical] get { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!_dynamicCodeGeneration.HasValue) { try { ((CodeAccessPermission)new ReflectionPermission((ReflectionPermissionFlag)2)).Demand(); ((CodeAccessPermission)new ReflectionPermission((ReflectionPermissionFlag)8)).Demand(); ((CodeAccessPermission)new SecurityPermission(SecurityPermissionFlag.SkipVerification)).Demand(); ((CodeAccessPermission)new SecurityPermission(SecurityPermissionFlag.UnmanagedCode)).Demand(); ((CodeAccessPermission)new SecurityPermission(PermissionState.Unrestricted)).Demand(); _dynamicCodeGeneration = true; } catch (Exception) { _dynamicCodeGeneration = false; } } return _dynamicCodeGeneration.GetValueOrDefault(); } } public static bool FullyTrusted { get { if (!_fullyTrusted.HasValue) { AppDomain currentDomain = AppDomain.CurrentDomain; _fullyTrusted = currentDomain.IsHomogenous && currentDomain.IsFullyTrusted; } return _fullyTrusted.GetValueOrDefault(); } } public static ReflectionDelegateFactory ReflectionDelegateFactory { get { if (DynamicCodeGeneration) { return DynamicReflectionDelegateFactory.Instance; } return LateBoundReflectionDelegateFactory.Instance; } } public static T? GetCachedAttribute(object attributeProvider) where T : Attribute { return CachedAttributeGetter.GetAttribute(attributeProvider); } public static bool CanTypeDescriptorConvertString(Type type, out TypeConverter typeConverter) { typeConverter = TypeDescriptor.GetConverter(type); if (typeConverter != null) { Type type2 = typeConverter.GetType(); if (!string.Equals(type2.FullName, "System.ComponentModel.ComponentConverter", StringComparison.Ordinal) && !string.Equals(type2.FullName, "System.ComponentModel.ReferenceConverter", StringComparison.Ordinal) && !string.Equals(type2.FullName, "System.Windows.Forms.Design.DataSourceConverter", StringComparison.Ordinal) && type2 != typeof(TypeConverter)) { return typeConverter.CanConvertTo(typeof(string)); } } return false; } public static DataContractAttribute? GetDataContractAttribute(Type type) { Type type2 = type; while (type2 != null) { DataContractAttribute attribute = CachedAttributeGetter.GetAttribute(type2); if (attribute != null) { return attribute; } type2 = type2.BaseType(); } return null; } public static DataMemberAttribute? GetDataMemberAttribute(MemberInfo memberInfo) { if (memberInfo.MemberType() == MemberTypes.Field) { return CachedAttributeGetter.GetAttribute(memberInfo); } PropertyInfo propertyInfo = (PropertyInfo)memberInfo; DataMemberAttribute attribute = CachedAttributeGetter.GetAttribute(propertyInfo); if (attribute == null && propertyInfo.IsVirtual()) { Type type = propertyInfo.DeclaringType; while (attribute == null && type != null) { PropertyInfo propertyInfo2 = (PropertyInfo)ReflectionUtils.GetMemberInfoFromType(type, propertyInfo); if (propertyInfo2 != null && propertyInfo2.IsVirtual()) { attribute = CachedAttributeGetter.GetAttribute(propertyInfo2); } type = type.BaseType(); } } return attribute; } public static MemberSerialization GetObjectMemberSerialization(Type objectType, bool ignoreSerializableAttribute) { JsonObjectAttribute cachedAttribute = GetCachedAttribute(objectType); if (cachedAttribute != null) { return cachedAttribute.MemberSerialization; } if (GetDataContractAttribute(objectType) != null) { return MemberSerialization.OptIn; } if (!ignoreSerializableAttribute && IsSerializable(objectType)) { return MemberSerialization.Fields; } return MemberSerialization.OptOut; } public static JsonConverter? GetJsonConverter(object attributeProvider) { JsonConverterAttribute cachedAttribute = GetCachedAttribute(attributeProvider); if (cachedAttribute != null) { Func func = CreatorCache.Get(cachedAttribute.ConverterType); if (func != null) { return (JsonConverter)func(cachedAttribute.ConverterParameters); } } return null; } public static JsonConverter CreateJsonConverterInstance(Type converterType, object[]? args) { return (JsonConverter)CreatorCache.Get(converterType)(args); } public static NamingStrategy CreateNamingStrategyInstance(Type namingStrategyType, object[]? args) { return (NamingStrategy)CreatorCache.Get(namingStrategyType)(args); } public static NamingStrategy? GetContainerNamingStrategy(JsonContainerAttribute containerAttribute) { if (containerAttribute.NamingStrategyInstance == null) { if (containerAttribute.NamingStrategyType == null) { return null; } containerAttribute.NamingStrategyInstance = CreateNamingStrategyInstance(containerAttribute.NamingStrategyType, containerAttribute.NamingStrategyParameters); } return containerAttribute.NamingStrategyInstance; } private static Func GetCreator(Type type) { Type type2 = type; Func defaultConstructor = (ReflectionUtils.HasDefaultConstructor(type2, nonPublic: false) ? ReflectionDelegateFactory.CreateDefaultConstructor(type2) : null); return delegate(object[]? parameters) { try { if (parameters != null) { Type[] types = parameters.Select(delegate(object param) { if (param == null) { throw new InvalidOperationException("Cannot pass a null parameter to the constructor."); } return param.GetType(); }).ToArray(); ConstructorInfo constructor = type2.GetConstructor(types); if (!(constructor != null)) { throw new JsonException("No matching parameterized constructor found for '{0}'.".FormatWith(CultureInfo.InvariantCulture, type2)); } return ReflectionDelegateFactory.CreateParameterizedConstructor(constructor)(parameters); } if (defaultConstructor == null) { throw new JsonException("No parameterless constructor defined for '{0}'.".FormatWith(CultureInfo.InvariantCulture, type2)); } return defaultConstructor(); } catch (Exception innerException) { throw new JsonException("Error creating '{0}'.".FormatWith(CultureInfo.InvariantCulture, type2), innerException); } }; } private static Type? GetAssociatedMetadataType(Type type) { return AssociatedMetadataTypesCache.Get(type); } private static Type? GetAssociateMetadataTypeFromAttribute(Type type) { Attribute[] attributes = ReflectionUtils.GetAttributes(type, null, inherit: true); foreach (Attribute attribute in attributes) { Type type2 = attribute.GetType(); if (string.Equals(type2.FullName, "System.ComponentModel.DataAnnotations.MetadataTypeAttribute", StringComparison.Ordinal)) { if (_metadataTypeAttributeReflectionObject == null) { _metadataTypeAttributeReflectionObject = ReflectionObject.Create(type2, "MetadataClassType"); } return (Type)_metadataTypeAttributeReflectionObject.GetValue(attribute, "MetadataClassType"); } } return null; } private static T? GetAttribute(Type type) where T : Attribute { Type associatedMetadataType = GetAssociatedMetadataType(type); T attribute; if (associatedMetadataType != null) { attribute = ReflectionUtils.GetAttribute(associatedMetadataType, inherit: true); if (attribute != null) { return attribute; } } attribute = ReflectionUtils.GetAttribute(type, inherit: true); if (attribute != null) { return attribute; } Type[] interfaces = type.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { attribute = ReflectionUtils.GetAttribute(interfaces[i], inherit: true); if (attribute != null) { return attribute; } } return null; } private static T? GetAttribute(MemberInfo memberInfo) where T : Attribute { Type associatedMetadataType = GetAssociatedMetadataType(memberInfo.DeclaringType); T attribute; if (associatedMetadataType != null) { MemberInfo memberInfoFromType = ReflectionUtils.GetMemberInfoFromType(associatedMetadataType, memberInfo); if (memberInfoFromType != null) { attribute = ReflectionUtils.GetAttribute(memberInfoFromType, inherit: true); if (attribute != null) { return attribute; } } } attribute = ReflectionUtils.GetAttribute(memberInfo, inherit: true); if (attribute != null) { return attribute; } if (memberInfo.DeclaringType != null) { Type[] interfaces = memberInfo.DeclaringType.GetInterfaces(); for (int i = 0; i < interfaces.Length; i++) { MemberInfo memberInfoFromType2 = ReflectionUtils.GetMemberInfoFromType(interfaces[i], memberInfo); if (memberInfoFromType2 != null) { attribute = ReflectionUtils.GetAttribute(memberInfoFromType2, inherit: true); if (attribute != null) { return attribute; } } } } return null; } public static bool IsNonSerializable(object provider) { return ReflectionUtils.GetAttribute(provider, inherit: false) != null; } public static bool IsSerializable(object provider) { return ReflectionUtils.GetAttribute(provider, inherit: false) != null; } public static T? GetAttribute(object provider) where T : Attribute { if (provider is Type type) { return GetAttribute(type); } if (provider is MemberInfo memberInfo) { return GetAttribute(memberInfo); } return ReflectionUtils.GetAttribute(provider, inherit: true); } } internal class KebabCaseNamingStrategy : NamingStrategy { public KebabCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) { base.ProcessDictionaryKeys = processDictionaryKeys; base.OverrideSpecifiedNames = overrideSpecifiedNames; } public KebabCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) : this(processDictionaryKeys, overrideSpecifiedNames) { base.ProcessExtensionDataNames = processExtensionDataNames; } public KebabCaseNamingStrategy() { } protected override string ResolvePropertyName(string name) { return StringUtils.ToKebabCase(name); } } internal class MemoryTraceWriter : ITraceWriter { private readonly Queue _traceMessages; private readonly object _lock; public TraceLevel LevelFilter { get; set; } public MemoryTraceWriter() { LevelFilter = TraceLevel.Verbose; _traceMessages = new Queue(); _lock = new object(); } public void Trace(TraceLevel level, string message, Exception? ex) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff", CultureInfo.InvariantCulture)); stringBuilder.Append(" "); stringBuilder.Append(level.ToString("g")); stringBuilder.Append(" "); stringBuilder.Append(message); string item = stringBuilder.ToString(); lock (_lock) { if (_traceMessages.Count >= 1000) { _traceMessages.Dequeue(); } _traceMessages.Enqueue(item); } } public IEnumerable GetTraceMessages() { return _traceMessages; } public override string ToString() { lock (_lock) { StringBuilder stringBuilder = new StringBuilder(); foreach (string traceMessage in _traceMessages) { if (stringBuilder.Length > 0) { stringBuilder.AppendLine(); } stringBuilder.Append(traceMessage); } return stringBuilder.ToString(); } } } internal abstract class NamingStrategy { public bool ProcessDictionaryKeys { get; set; } public bool ProcessExtensionDataNames { get; set; } public bool OverrideSpecifiedNames { get; set; } public virtual string GetPropertyName(string name, bool hasSpecifiedName) { if (hasSpecifiedName && !OverrideSpecifiedNames) { return name; } return ResolvePropertyName(name); } public virtual string GetExtensionDataName(string name) { if (!ProcessExtensionDataNames) { return name; } return ResolvePropertyName(name); } public virtual string GetDictionaryKey(string key) { if (!ProcessDictionaryKeys) { return key; } return ResolvePropertyName(key); } protected abstract string ResolvePropertyName(string name); public override int GetHashCode() { return (((((GetType().GetHashCode() * 397) ^ ProcessDictionaryKeys.GetHashCode()) * 397) ^ ProcessExtensionDataNames.GetHashCode()) * 397) ^ OverrideSpecifiedNames.GetHashCode(); } public override bool Equals(object? obj) { return Equals(obj as NamingStrategy); } protected bool Equals(NamingStrategy? other) { if (other == null) { return false; } if (GetType() == other.GetType() && ProcessDictionaryKeys == other.ProcessDictionaryKeys && ProcessExtensionDataNames == other.ProcessExtensionDataNames) { return OverrideSpecifiedNames == other.OverrideSpecifiedNames; } return false; } } internal delegate object ObjectConstructor(params object?[] args); [AttributeUsage(AttributeTargets.Method, Inherited = false)] internal sealed class OnErrorAttribute : Attribute { } internal class ReflectionAttributeProvider : IAttributeProvider { private readonly object _attributeProvider; public ReflectionAttributeProvider(object attributeProvider) { ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider"); _attributeProvider = attributeProvider; } public IList GetAttributes(bool inherit) { return ReflectionUtils.GetAttributes(_attributeProvider, null, inherit); } public IList GetAttributes(Type attributeType, bool inherit) { return ReflectionUtils.GetAttributes(_attributeProvider, attributeType, inherit); } } internal class ReflectionValueProvider : IValueProvider { private readonly MemberInfo _memberInfo; public ReflectionValueProvider(MemberInfo memberInfo) { ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo"); _memberInfo = memberInfo; } public void SetValue(object target, object? value) { try { ReflectionUtils.SetMemberValue(_memberInfo, target, value); } catch (Exception innerException) { throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } public object? GetValue(object target) { try { if (_memberInfo is PropertyInfo propertyInfo && propertyInfo.PropertyType.IsByRef) { throw new InvalidOperationException("Could not create getter for {0}. ByRef return values are not supported.".FormatWith(CultureInfo.InvariantCulture, propertyInfo)); } return ReflectionUtils.GetMemberValue(_memberInfo, target); } catch (Exception innerException) { throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), innerException); } } } internal class SerializationBinderAdapter : ISerializationBinder { public readonly SerializationBinder SerializationBinder; public SerializationBinderAdapter(SerializationBinder serializationBinder) { SerializationBinder = serializationBinder; } public Type BindToType(string? assemblyName, string typeName) { return SerializationBinder.BindToType(assemblyName, typeName); } public void BindToName(Type serializedType, out string? assemblyName, out string? typeName) { SerializationBinder.BindToName(serializedType, out assemblyName, out typeName); } } internal class SnakeCaseNamingStrategy : NamingStrategy { public SnakeCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames) { base.ProcessDictionaryKeys = processDictionaryKeys; base.OverrideSpecifiedNames = overrideSpecifiedNames; } public SnakeCaseNamingStrategy(bool processDictionaryKeys, bool overrideSpecifiedNames, bool processExtensionDataNames) : this(processDictionaryKeys, overrideSpecifiedNames) { base.ProcessExtensionDataNames = processExtensionDataNames; } public SnakeCaseNamingStrategy() { } protected override string ResolvePropertyName(string name) { return StringUtils.ToSnakeCase(name); } } internal class TraceJsonReader : JsonReader, IJsonLineInfo { private readonly JsonReader _innerReader; private readonly JsonTextWriter _textWriter; private readonly StringWriter _sw; public override int Depth => _innerReader.Depth; public override string Path => _innerReader.Path; public override char QuoteChar { get { return _innerReader.QuoteChar; } protected internal set { _innerReader.QuoteChar = value; } } public override JsonToken TokenType => _innerReader.TokenType; public override object? Value => _innerReader.Value; public override Type? ValueType => _innerReader.ValueType; int IJsonLineInfo.LineNumber { get { if (!(_innerReader is IJsonLineInfo jsonLineInfo)) { return 0; } return jsonLineInfo.LineNumber; } } int IJsonLineInfo.LinePosition { get { if (!(_innerReader is IJsonLineInfo jsonLineInfo)) { return 0; } return jsonLineInfo.LinePosition; } } public TraceJsonReader(JsonReader innerReader) { _innerReader = innerReader; _sw = new StringWriter(CultureInfo.InvariantCulture); _sw.Write("Deserialized JSON: " + Environment.NewLine); _textWriter = new JsonTextWriter(_sw); _textWriter.Formatting = Formatting.Indented; } public string GetDeserializedJsonMessage() { return _sw.ToString(); } public override bool Read() { bool result = _innerReader.Read(); WriteCurrentToken(); return result; } public override int? ReadAsInt32() { int? result = _innerReader.ReadAsInt32(); WriteCurrentToken(); return result; } public override string? ReadAsString() { string? result = _innerReader.ReadAsString(); WriteCurrentToken(); return result; } public override byte[]? ReadAsBytes() { byte[]? result = _innerReader.ReadAsBytes(); WriteCurrentToken(); return result; } public override decimal? ReadAsDecimal() { decimal? result = _innerReader.ReadAsDecimal(); WriteCurrentToken(); return result; } public override double? ReadAsDouble() { double? result = _innerReader.ReadAsDouble(); WriteCurrentToken(); return result; } public override bool? ReadAsBoolean() { bool? result = _innerReader.ReadAsBoolean(); WriteCurrentToken(); return result; } public override DateTime? ReadAsDateTime() { DateTime? result = _innerReader.ReadAsDateTime(); WriteCurrentToken(); return result; } public override DateTimeOffset? ReadAsDateTimeOffset() { DateTimeOffset? result = _innerReader.ReadAsDateTimeOffset(); WriteCurrentToken(); return result; } public void WriteCurrentToken() { _textWriter.WriteToken(_innerReader, writeChildren: false, writeDateConstructorAsDate: false, writeComments: true); } public override void Close() { _innerReader.Close(); } bool IJsonLineInfo.HasLineInfo() { if (_innerReader is IJsonLineInfo jsonLineInfo) { return jsonLineInfo.HasLineInfo(); } return false; } } internal class TraceJsonWriter : JsonWriter { private readonly JsonWriter _innerWriter; private readonly JsonTextWriter _textWriter; private readonly StringWriter _sw; public TraceJsonWriter(JsonWriter innerWriter) { _innerWriter = innerWriter; _sw = new StringWriter(CultureInfo.InvariantCulture); _sw.Write("Serialized JSON: " + Environment.NewLine); _textWriter = new JsonTextWriter(_sw); _textWriter.Formatting = Formatting.Indented; _textWriter.Culture = innerWriter.Culture; _textWriter.DateFormatHandling = innerWriter.DateFormatHandling; _textWriter.DateFormatString = innerWriter.DateFormatString; _textWriter.DateTimeZoneHandling = innerWriter.DateTimeZoneHandling; _textWriter.FloatFormatHandling = innerWriter.FloatFormatHandling; } public string GetSerializedJsonMessage() { return _sw.ToString(); } public override void WriteValue(decimal value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(decimal? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(bool value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(bool? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(byte value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(byte? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(char value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(char? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(byte[]? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value == null) { base.WriteUndefined(); } else { base.WriteValue(value); } } public override void WriteValue(DateTime value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(DateTime? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(DateTimeOffset value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(DateTimeOffset? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(double value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(double? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteUndefined() { _textWriter.WriteUndefined(); _innerWriter.WriteUndefined(); base.WriteUndefined(); } public override void WriteNull() { _textWriter.WriteNull(); _innerWriter.WriteNull(); base.WriteUndefined(); } public override void WriteValue(float value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(float? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(Guid value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(Guid? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(int value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(int? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(long value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(long? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(object? value) { if (value is BigInteger) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); InternalWriteValue(JsonToken.Integer); return; } _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value == null) { base.WriteUndefined(); } else { InternalWriteValue(JsonToken.String); } } public override void WriteValue(sbyte value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(sbyte? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(short value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(short? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(string? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(TimeSpan value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(TimeSpan? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(uint value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(uint? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(ulong value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(ulong? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteValue(Uri? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value == null) { base.WriteUndefined(); } else { base.WriteValue(value); } } public override void WriteValue(ushort value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); base.WriteValue(value); } public override void WriteValue(ushort? value) { _textWriter.WriteValue(value); _innerWriter.WriteValue(value); if (value.HasValue) { base.WriteValue(value.GetValueOrDefault()); } else { base.WriteUndefined(); } } public override void WriteWhitespace(string ws) { _textWriter.WriteWhitespace(ws); _innerWriter.WriteWhitespace(ws); base.WriteWhitespace(ws); } public override void WriteComment(string? text) { _textWriter.WriteComment(text); _innerWriter.WriteComment(text); base.WriteComment(text); } public override void WriteStartArray() { _textWriter.WriteStartArray(); _innerWriter.WriteStartArray(); base.WriteStartArray(); } public override void WriteEndArray() { _textWriter.WriteEndArray(); _innerWriter.WriteEndArray(); base.WriteEndArray(); } public override void WriteStartConstructor(string name) { _textWriter.WriteStartConstructor(name); _innerWriter.WriteStartConstructor(name); base.WriteStartConstructor(name); } public override void WriteEndConstructor() { _textWriter.WriteEndConstructor(); _innerWriter.WriteEndConstructor(); base.WriteEndConstructor(); } public override void WritePropertyName(string name) { _textWriter.WritePropertyName(name); _innerWriter.WritePropertyName(name); base.WritePropertyName(name); } public override void WritePropertyName(string name, bool escape) { _textWriter.WritePropertyName(name, escape); _innerWriter.WritePropertyName(name, escape); base.WritePropertyName(name); } public override void WriteStartObject() { _textWriter.WriteStartObject(); _innerWriter.WriteStartObject(); base.WriteStartObject(); } public override void WriteEndObject() { _textWriter.WriteEndObject(); _innerWriter.WriteEndObject(); base.WriteEndObject(); } public override void WriteRawValue(string? json) { _textWriter.WriteRawValue(json); _innerWriter.WriteRawValue(json); InternalWriteValue(JsonToken.Undefined); } public override void WriteRaw(string? json) { _textWriter.WriteRaw(json); _innerWriter.WriteRaw(json); base.WriteRaw(json); } public override void Close() { _textWriter.Close(); _innerWriter.Close(); base.Close(); } public override void Flush() { _textWriter.Flush(); _innerWriter.Flush(); } } } namespace Newtonsoft.Json.Schema { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal static class Extensions { [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] public static bool IsValid(this JToken source, JsonSchema schema) { bool valid = true; source.Validate(schema, delegate { valid = false; }); return valid; } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] public static bool IsValid(this JToken source, JsonSchema schema, out IList errorMessages) { IList errors = new List(); source.Validate(schema, delegate(object sender, ValidationEventArgs args) { errors.Add(args.Message); }); errorMessages = errors; return errorMessages.Count == 0; } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] public static void Validate(this JToken source, JsonSchema schema) { source.Validate(schema, null); } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] public static void Validate(this JToken source, JsonSchema schema, ValidationEventHandler validationEventHandler) { ValidationUtils.ArgumentNotNull(source, "source"); ValidationUtils.ArgumentNotNull(schema, "schema"); using JsonValidatingReader jsonValidatingReader = new JsonValidatingReader(source.CreateReader()); jsonValidatingReader.Schema = schema; if (validationEventHandler != null) { jsonValidatingReader.ValidationEventHandler += validationEventHandler; } while (jsonValidatingReader.Read()) { } } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchema { private readonly string _internalId = Guid.NewGuid().ToString("N"); public string Id { get; set; } public string Title { get; set; } public bool? Required { get; set; } public bool? ReadOnly { get; set; } public bool? Hidden { get; set; } public bool? Transient { get; set; } public string Description { get; set; } public JsonSchemaType? Type { get; set; } public string Pattern { get; set; } public int? MinimumLength { get; set; } public int? MaximumLength { get; set; } public double? DivisibleBy { get; set; } public double? Minimum { get; set; } public double? Maximum { get; set; } public bool? ExclusiveMinimum { get; set; } public bool? ExclusiveMaximum { get; set; } public int? MinimumItems { get; set; } public int? MaximumItems { get; set; } public IList Items { get; set; } public bool PositionalItemsValidation { get; set; } public JsonSchema AdditionalItems { get; set; } public bool AllowAdditionalItems { get; set; } public bool UniqueItems { get; set; } public IDictionary Properties { get; set; } public JsonSchema AdditionalProperties { get; set; } public IDictionary PatternProperties { get; set; } public bool AllowAdditionalProperties { get; set; } public string Requires { get; set; } public IList Enum { get; set; } public JsonSchemaType? Disallow { get; set; } public JToken Default { get; set; } public IList Extends { get; set; } public string Format { get; set; } internal string Location { get; set; } internal string InternalId => _internalId; internal string DeferredReference { get; set; } internal bool ReferencesResolved { get; set; } public JsonSchema() { AllowAdditionalProperties = true; AllowAdditionalItems = true; } public static JsonSchema Read(JsonReader reader) { return Read(reader, new JsonSchemaResolver()); } public static JsonSchema Read(JsonReader reader, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(resolver, "resolver"); return new JsonSchemaBuilder(resolver).Read(reader); } public static JsonSchema Parse(string json) { return Parse(json, new JsonSchemaResolver()); } public static JsonSchema Parse(string json, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(json, "json"); using JsonReader reader = new JsonTextReader(new StringReader(json)); return Read(reader, resolver); } public void WriteTo(JsonWriter writer) { WriteTo(writer, new JsonSchemaResolver()); } public void WriteTo(JsonWriter writer, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(writer, "writer"); ValidationUtils.ArgumentNotNull(resolver, "resolver"); new JsonSchemaWriter(writer, resolver).WriteSchema(this); } public override string ToString() { StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); WriteTo(new JsonTextWriter(stringWriter) { Formatting = Formatting.Indented }); return stringWriter.ToString(); } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaBuilder { private readonly IList _stack; private readonly JsonSchemaResolver _resolver; private readonly IDictionary _documentSchemas; private JsonSchema _currentSchema; private JObject _rootSchema; private JsonSchema CurrentSchema => _currentSchema; public JsonSchemaBuilder(JsonSchemaResolver resolver) { _stack = new List(); _documentSchemas = new Dictionary(); _resolver = resolver; } private void Push(JsonSchema value) { _currentSchema = value; _stack.Add(value); _resolver.LoadedSchemas.Add(value); _documentSchemas.Add(value.Location, value); } private JsonSchema Pop() { JsonSchema currentSchema = _currentSchema; _stack.RemoveAt(_stack.Count - 1); _currentSchema = _stack.LastOrDefault(); return currentSchema; } internal JsonSchema Read(JsonReader reader) { JToken jToken = JToken.ReadFrom(reader); _rootSchema = jToken as JObject; JsonSchema jsonSchema = BuildSchema(jToken); ResolveReferences(jsonSchema); return jsonSchema; } private string UnescapeReference(string reference) { return StringUtils.Replace(StringUtils.Replace(Uri.UnescapeDataString(reference), "~1", "/"), "~0", "~"); } private JsonSchema ResolveReferences(JsonSchema schema) { if (schema.DeferredReference != null) { string text = schema.DeferredReference; bool flag = text.StartsWith("#", StringComparison.Ordinal); if (flag) { text = UnescapeReference(text); } JsonSchema jsonSchema = _resolver.GetSchema(text); if (jsonSchema == null) { if (flag) { string[] array = schema.DeferredReference.TrimStart(new char[1] { '#' }).Split(new char[1] { '/' }, StringSplitOptions.RemoveEmptyEntries); JToken jToken = _rootSchema; string[] array2 = array; foreach (string reference in array2) { string text2 = UnescapeReference(reference); if (jToken.Type == JTokenType.Object) { jToken = jToken[text2]; } else if (jToken.Type == JTokenType.Array || jToken.Type == JTokenType.Constructor) { jToken = ((!int.TryParse(text2, out var result) || result < 0 || result >= jToken.Count()) ? null : jToken[result]); } if (jToken == null) { break; } } if (jToken != null) { jsonSchema = BuildSchema(jToken); } } if (jsonSchema == null) { throw new JsonException("Could not resolve schema reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, schema.DeferredReference)); } } schema = jsonSchema; } if (schema.ReferencesResolved) { return schema; } schema.ReferencesResolved = true; if (schema.Extends != null) { for (int j = 0; j < schema.Extends.Count; j++) { schema.Extends[j] = ResolveReferences(schema.Extends[j]); } } if (schema.Items != null) { for (int k = 0; k < schema.Items.Count; k++) { schema.Items[k] = ResolveReferences(schema.Items[k]); } } if (schema.AdditionalItems != null) { schema.AdditionalItems = ResolveReferences(schema.AdditionalItems); } if (schema.PatternProperties != null) { foreach (KeyValuePair item in schema.PatternProperties.ToList()) { schema.PatternProperties[item.Key] = ResolveReferences(item.Value); } } if (schema.Properties != null) { foreach (KeyValuePair item2 in schema.Properties.ToList()) { schema.Properties[item2.Key] = ResolveReferences(item2.Value); } } if (schema.AdditionalProperties != null) { schema.AdditionalProperties = ResolveReferences(schema.AdditionalProperties); } return schema; } private JsonSchema BuildSchema(JToken token) { if (!(token is JObject jObject)) { throw JsonException.Create(token, token.Path, "Expected object while parsing schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } if (jObject.TryGetValue("$ref", out JToken value)) { return new JsonSchema { DeferredReference = (string?)value }; } string path = token.Path; path = StringUtils.Replace(path, ".", "/"); path = StringUtils.Replace(path, "[", "/"); path = StringUtils.Replace(path, "]", string.Empty); if (!StringUtils.IsNullOrEmpty(path)) { path = "/" + path; } path = "#" + path; if (_documentSchemas.TryGetValue(path, out var value2)) { return value2; } Push(new JsonSchema { Location = path }); ProcessSchemaProperties(jObject); return Pop(); } private void ProcessSchemaProperties(JObject schemaObject) { foreach (KeyValuePair item in schemaObject) { switch (item.Key) { case "type": CurrentSchema.Type = ProcessType(item.Value); break; case "id": CurrentSchema.Id = (string?)item.Value; break; case "title": CurrentSchema.Title = (string?)item.Value; break; case "description": CurrentSchema.Description = (string?)item.Value; break; case "properties": CurrentSchema.Properties = ProcessProperties(item.Value); break; case "items": ProcessItems(item.Value); break; case "additionalProperties": ProcessAdditionalProperties(item.Value); break; case "additionalItems": ProcessAdditionalItems(item.Value); break; case "patternProperties": CurrentSchema.PatternProperties = ProcessProperties(item.Value); break; case "required": CurrentSchema.Required = (bool)item.Value; break; case "requires": CurrentSchema.Requires = (string?)item.Value; break; case "minimum": CurrentSchema.Minimum = (double)item.Value; break; case "maximum": CurrentSchema.Maximum = (double)item.Value; break; case "exclusiveMinimum": CurrentSchema.ExclusiveMinimum = (bool)item.Value; break; case "exclusiveMaximum": CurrentSchema.ExclusiveMaximum = (bool)item.Value; break; case "maxLength": CurrentSchema.MaximumLength = (int)item.Value; break; case "minLength": CurrentSchema.MinimumLength = (int)item.Value; break; case "maxItems": CurrentSchema.MaximumItems = (int)item.Value; break; case "minItems": CurrentSchema.MinimumItems = (int)item.Value; break; case "divisibleBy": CurrentSchema.DivisibleBy = (double)item.Value; break; case "disallow": CurrentSchema.Disallow = ProcessType(item.Value); break; case "default": CurrentSchema.Default = item.Value.DeepClone(); break; case "hidden": CurrentSchema.Hidden = (bool)item.Value; break; case "readonly": CurrentSchema.ReadOnly = (bool)item.Value; break; case "format": CurrentSchema.Format = (string?)item.Value; break; case "pattern": CurrentSchema.Pattern = (string?)item.Value; break; case "enum": ProcessEnum(item.Value); break; case "extends": ProcessExtends(item.Value); break; case "uniqueItems": CurrentSchema.UniqueItems = (bool)item.Value; break; } } } private void ProcessExtends(JToken token) { IList list = new List(); if (token.Type == JTokenType.Array) { foreach (JToken item in (IEnumerable)token) { list.Add(BuildSchema(item)); } } else { JsonSchema jsonSchema = BuildSchema(token); if (jsonSchema != null) { list.Add(jsonSchema); } } if (list.Count > 0) { CurrentSchema.Extends = list; } } private void ProcessEnum(JToken token) { if (token.Type != JTokenType.Array) { throw JsonException.Create(token, token.Path, "Expected Array token while parsing enum values, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } CurrentSchema.Enum = new List(); foreach (JToken item in (IEnumerable)token) { CurrentSchema.Enum.Add(item.DeepClone()); } } private void ProcessAdditionalProperties(JToken token) { if (token.Type == JTokenType.Boolean) { CurrentSchema.AllowAdditionalProperties = (bool)token; } else { CurrentSchema.AdditionalProperties = BuildSchema(token); } } private void ProcessAdditionalItems(JToken token) { if (token.Type == JTokenType.Boolean) { CurrentSchema.AllowAdditionalItems = (bool)token; } else { CurrentSchema.AdditionalItems = BuildSchema(token); } } private IDictionary ProcessProperties(JToken token) { IDictionary dictionary = new Dictionary(); if (token.Type != JTokenType.Object) { throw JsonException.Create(token, token.Path, "Expected Object token while parsing schema properties, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } foreach (JProperty item in (IEnumerable)token) { if (dictionary.ContainsKey(item.Name)) { throw new JsonException("Property {0} has already been defined in schema.".FormatWith(CultureInfo.InvariantCulture, item.Name)); } dictionary.Add(item.Name, BuildSchema(item.Value)); } return dictionary; } private void ProcessItems(JToken token) { CurrentSchema.Items = new List(); switch (token.Type) { case JTokenType.Object: CurrentSchema.Items.Add(BuildSchema(token)); CurrentSchema.PositionalItemsValidation = false; break; case JTokenType.Array: CurrentSchema.PositionalItemsValidation = true; { foreach (JToken item in (IEnumerable)token) { CurrentSchema.Items.Add(BuildSchema(item)); } break; } default: throw JsonException.Create(token, token.Path, "Expected array or JSON schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } } private JsonSchemaType? ProcessType(JToken token) { switch (token.Type) { case JTokenType.Array: { JsonSchemaType? jsonSchemaType = JsonSchemaType.None; { foreach (JToken item in (IEnumerable)token) { if (item.Type != JTokenType.String) { throw JsonException.Create(item, item.Path, "Expected JSON schema type string token, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } jsonSchemaType |= MapType((string?)item); } return jsonSchemaType; } } case JTokenType.String: return MapType((string?)token); default: throw JsonException.Create(token, token.Path, "Expected array or JSON schema type string token, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type)); } } internal static JsonSchemaType MapType(string type) { if (!JsonSchemaConstants.JsonSchemaTypeMapping.TryGetValue(type, out var value)) { throw new JsonException("Invalid JSON schema type: {0}".FormatWith(CultureInfo.InvariantCulture, type)); } return value; } internal static string MapType(JsonSchemaType type) { return JsonSchemaConstants.JsonSchemaTypeMapping.Single((KeyValuePair kv) => kv.Value == type).Key; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal static class JsonSchemaConstants { public const string TypePropertyName = "type"; public const string PropertiesPropertyName = "properties"; public const string ItemsPropertyName = "items"; public const string AdditionalItemsPropertyName = "additionalItems"; public const string RequiredPropertyName = "required"; public const string PatternPropertiesPropertyName = "patternProperties"; public const string AdditionalPropertiesPropertyName = "additionalProperties"; public const string RequiresPropertyName = "requires"; public const string MinimumPropertyName = "minimum"; public const string MaximumPropertyName = "maximum"; public const string ExclusiveMinimumPropertyName = "exclusiveMinimum"; public const string ExclusiveMaximumPropertyName = "exclusiveMaximum"; public const string MinimumItemsPropertyName = "minItems"; public const string MaximumItemsPropertyName = "maxItems"; public const string PatternPropertyName = "pattern"; public const string MaximumLengthPropertyName = "maxLength"; public const string MinimumLengthPropertyName = "minLength"; public const string EnumPropertyName = "enum"; public const string ReadOnlyPropertyName = "readonly"; public const string TitlePropertyName = "title"; public const string DescriptionPropertyName = "description"; public const string FormatPropertyName = "format"; public const string DefaultPropertyName = "default"; public const string TransientPropertyName = "transient"; public const string DivisibleByPropertyName = "divisibleBy"; public const string HiddenPropertyName = "hidden"; public const string DisallowPropertyName = "disallow"; public const string ExtendsPropertyName = "extends"; public const string IdPropertyName = "id"; public const string UniqueItemsPropertyName = "uniqueItems"; public const string OptionValuePropertyName = "value"; public const string OptionLabelPropertyName = "label"; public static readonly IDictionary JsonSchemaTypeMapping = new Dictionary { { "string", JsonSchemaType.String }, { "object", JsonSchemaType.Object }, { "integer", JsonSchemaType.Integer }, { "number", JsonSchemaType.Float }, { "null", JsonSchemaType.Null }, { "boolean", JsonSchemaType.Boolean }, { "array", JsonSchemaType.Array }, { "any", JsonSchemaType.Any } }; } [Serializable] [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string Path { get; } public JsonSchemaException() { } public JsonSchemaException(string message) : base(message) { } public JsonSchemaException(string message, Exception innerException) : base(message, innerException) { } public JsonSchemaException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal JsonSchemaException(string message, Exception innerException, string path, int lineNumber, int linePosition) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaGenerator { private class TypeSchema { public Type Type { get; } public JsonSchema Schema { get; } public TypeSchema(Type type, JsonSchema schema) { ValidationUtils.ArgumentNotNull(type, "type"); ValidationUtils.ArgumentNotNull(schema, "schema"); Type = type; Schema = schema; } } private IContractResolver _contractResolver; private JsonSchemaResolver _resolver; private readonly IList _stack = new List(); private JsonSchema _currentSchema; public UndefinedSchemaIdHandling UndefinedSchemaIdHandling { get; set; } public IContractResolver ContractResolver { get { if (_contractResolver == null) { return DefaultContractResolver.Instance; } return _contractResolver; } set { _contractResolver = value; } } private JsonSchema CurrentSchema => _currentSchema; private void Push(TypeSchema typeSchema) { _currentSchema = typeSchema.Schema; _stack.Add(typeSchema); _resolver.LoadedSchemas.Add(typeSchema.Schema); } private TypeSchema Pop() { TypeSchema result = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); TypeSchema typeSchema = _stack.LastOrDefault(); if (typeSchema != null) { _currentSchema = typeSchema.Schema; return result; } _currentSchema = null; return result; } public JsonSchema Generate(Type type) { return Generate(type, new JsonSchemaResolver(), rootSchemaNullable: false); } public JsonSchema Generate(Type type, JsonSchemaResolver resolver) { return Generate(type, resolver, rootSchemaNullable: false); } public JsonSchema Generate(Type type, bool rootSchemaNullable) { return Generate(type, new JsonSchemaResolver(), rootSchemaNullable); } public JsonSchema Generate(Type type, JsonSchemaResolver resolver, bool rootSchemaNullable) { ValidationUtils.ArgumentNotNull(type, "type"); ValidationUtils.ArgumentNotNull(resolver, "resolver"); _resolver = resolver; return GenerateInternal(type, (!rootSchemaNullable) ? Required.Always : Required.Default, required: false); } private string GetTitle(Type type) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(type); if (!StringUtils.IsNullOrEmpty(cachedAttribute?.Title)) { return cachedAttribute.Title; } return null; } private string GetDescription(Type type) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(type); if (!StringUtils.IsNullOrEmpty(cachedAttribute?.Description)) { return cachedAttribute.Description; } return ReflectionUtils.GetAttribute(type)?.Description; } private string GetTypeId(Type type, bool explicitOnly) { JsonContainerAttribute cachedAttribute = JsonTypeReflector.GetCachedAttribute(type); if (!StringUtils.IsNullOrEmpty(cachedAttribute?.Id)) { return cachedAttribute.Id; } if (explicitOnly) { return null; } return UndefinedSchemaIdHandling switch { UndefinedSchemaIdHandling.UseTypeName => type.FullName, UndefinedSchemaIdHandling.UseAssemblyQualifiedName => type.AssemblyQualifiedName, _ => null, }; } private JsonSchema GenerateInternal(Type type, Required valueRequired, bool required) { ValidationUtils.ArgumentNotNull(type, "type"); string typeId = GetTypeId(type, explicitOnly: false); string typeId2 = GetTypeId(type, explicitOnly: true); if (!StringUtils.IsNullOrEmpty(typeId)) { JsonSchema schema = _resolver.GetSchema(typeId); if (schema != null) { if (valueRequired != Required.Always && !HasFlag(schema.Type, JsonSchemaType.Null)) { schema.Type |= JsonSchemaType.Null; } if (required && schema.Required != true) { schema.Required = true; } return schema; } } if (_stack.Any((TypeSchema tc) => tc.Type == type)) { throw new JsonException("Unresolved circular reference for type '{0}'. Explicitly define an Id for the type using a JsonObject/JsonArray attribute or automatically generate a type Id using the UndefinedSchemaIdHandling property.".FormatWith(CultureInfo.InvariantCulture, type)); } JsonContract jsonContract = ContractResolver.ResolveContract(type); JsonConverter? obj = jsonContract.Converter ?? jsonContract.InternalConverter; Push(new TypeSchema(type, new JsonSchema())); if (typeId2 != null) { CurrentSchema.Id = typeId2; } if (required) { CurrentSchema.Required = true; } CurrentSchema.Title = GetTitle(type); CurrentSchema.Description = GetDescription(type); if (obj != null) { CurrentSchema.Type = JsonSchemaType.Any; } else { switch (jsonContract.ContractType) { case JsonContractType.Object: CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); CurrentSchema.Id = GetTypeId(type, explicitOnly: false); GenerateObjectSchema(type, (JsonObjectContract)jsonContract); break; case JsonContractType.Array: { CurrentSchema.Type = AddNullType(JsonSchemaType.Array, valueRequired); CurrentSchema.Id = GetTypeId(type, explicitOnly: false); bool flag = JsonTypeReflector.GetCachedAttribute(type)?.AllowNullItems ?? true; Type collectionItemType = ReflectionUtils.GetCollectionItemType(type); if (collectionItemType != null) { CurrentSchema.Items = new List(); CurrentSchema.Items.Add(GenerateInternal(collectionItemType, (!flag) ? Required.Always : Required.Default, required: false)); } break; } case JsonContractType.Primitive: CurrentSchema.Type = GetJsonSchemaType(type, valueRequired); if (CurrentSchema.Type == JsonSchemaType.Integer && type.IsEnum() && !type.IsDefined(typeof(FlagsAttribute), inherit: true)) { CurrentSchema.Enum = new List(); EnumInfo enumValuesAndNames = EnumUtils.GetEnumValuesAndNames(type); for (int i = 0; i < enumValuesAndNames.Names.Length; i++) { ulong value = enumValuesAndNames.Values[i]; JToken item = JToken.FromObject(Enum.ToObject(type, value)); CurrentSchema.Enum.Add(item); } } break; case JsonContractType.String: { JsonSchemaType value2 = ((!ReflectionUtils.IsNullable(jsonContract.UnderlyingType)) ? JsonSchemaType.String : AddNullType(JsonSchemaType.String, valueRequired)); CurrentSchema.Type = value2; break; } case JsonContractType.Dictionary: { CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); ReflectionUtils.GetDictionaryKeyValueTypes(type, out Type keyType, out Type valueType); if (keyType != null && ContractResolver.ResolveContract(keyType).ContractType == JsonContractType.Primitive) { CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, required: false); } break; } case JsonContractType.Serializable: CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired); CurrentSchema.Id = GetTypeId(type, explicitOnly: false); GenerateISerializableContract(type, (JsonISerializableContract)jsonContract); break; case JsonContractType.Dynamic: case JsonContractType.Linq: CurrentSchema.Type = JsonSchemaType.Any; break; default: throw new JsonException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContract)); } } return Pop().Schema; } private JsonSchemaType AddNullType(JsonSchemaType type, Required valueRequired) { if (valueRequired != Required.Always) { return type | JsonSchemaType.Null; } return type; } private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag) { return (value & flag) == flag; } private void GenerateObjectSchema(Type type, JsonObjectContract contract) { CurrentSchema.Properties = new Dictionary(); foreach (JsonProperty property in contract.Properties) { if (!property.Ignored) { bool flag = property.NullValueHandling == NullValueHandling.Ignore || HasFlag(property.DefaultValueHandling.GetValueOrDefault(), DefaultValueHandling.Ignore) || property.ShouldSerialize != null || property.GetIsSpecified != null; JsonSchema jsonSchema = GenerateInternal(property.PropertyType, property.Required, !flag); if (property.DefaultValue != null) { jsonSchema.Default = JToken.FromObject(property.DefaultValue); } CurrentSchema.Properties.Add(property.PropertyName, jsonSchema); } } if (type.IsSealed()) { CurrentSchema.AllowAdditionalProperties = false; } } private void GenerateISerializableContract(Type type, JsonISerializableContract contract) { CurrentSchema.AllowAdditionalProperties = true; } internal static bool HasFlag(JsonSchemaType? value, JsonSchemaType flag) { if (!value.HasValue) { return true; } if ((value & flag) == flag) { return true; } if (flag == JsonSchemaType.Integer && ((uint?)value & 2u) == 2) { return true; } return false; } private JsonSchemaType GetJsonSchemaType(Type type, Required valueRequired) { JsonSchemaType jsonSchemaType = JsonSchemaType.None; if (valueRequired != Required.Always && ReflectionUtils.IsNullable(type)) { jsonSchemaType = JsonSchemaType.Null; if (ReflectionUtils.IsNullableType(type)) { type = Nullable.GetUnderlyingType(type); } } PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(type); switch (typeCode) { case PrimitiveTypeCode.Empty: case PrimitiveTypeCode.Object: return jsonSchemaType | JsonSchemaType.String; case PrimitiveTypeCode.DBNull: return jsonSchemaType | JsonSchemaType.Null; case PrimitiveTypeCode.Boolean: return jsonSchemaType | JsonSchemaType.Boolean; case PrimitiveTypeCode.Char: return jsonSchemaType | JsonSchemaType.String; case PrimitiveTypeCode.SByte: case PrimitiveTypeCode.Int16: case PrimitiveTypeCode.UInt16: case PrimitiveTypeCode.Int32: case PrimitiveTypeCode.Byte: case PrimitiveTypeCode.UInt32: case PrimitiveTypeCode.Int64: case PrimitiveTypeCode.UInt64: case PrimitiveTypeCode.BigInteger: return jsonSchemaType | JsonSchemaType.Integer; case PrimitiveTypeCode.Single: case PrimitiveTypeCode.Double: case PrimitiveTypeCode.Decimal: return jsonSchemaType | JsonSchemaType.Float; case PrimitiveTypeCode.DateTime: case PrimitiveTypeCode.DateTimeOffset: return jsonSchemaType | JsonSchemaType.String; case PrimitiveTypeCode.Guid: case PrimitiveTypeCode.TimeSpan: case PrimitiveTypeCode.Uri: case PrimitiveTypeCode.String: case PrimitiveTypeCode.Bytes: return jsonSchemaType | JsonSchemaType.String; default: throw new JsonException("Unexpected type code '{0}' for type '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeCode, type)); } } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaModel { public bool Required { get; set; } public JsonSchemaType Type { get; set; } public int? MinimumLength { get; set; } public int? MaximumLength { get; set; } public double? DivisibleBy { get; set; } public double? Minimum { get; set; } public double? Maximum { get; set; } public bool ExclusiveMinimum { get; set; } public bool ExclusiveMaximum { get; set; } public int? MinimumItems { get; set; } public int? MaximumItems { get; set; } public IList Patterns { get; set; } public IList Items { get; set; } public IDictionary Properties { get; set; } public IDictionary PatternProperties { get; set; } public JsonSchemaModel AdditionalProperties { get; set; } public JsonSchemaModel AdditionalItems { get; set; } public bool PositionalItemsValidation { get; set; } public bool AllowAdditionalProperties { get; set; } public bool AllowAdditionalItems { get; set; } public bool UniqueItems { get; set; } public IList Enum { get; set; } public JsonSchemaType Disallow { get; set; } public JsonSchemaModel() { Type = JsonSchemaType.Any; AllowAdditionalProperties = true; AllowAdditionalItems = true; Required = false; } public static JsonSchemaModel Create(IList schemata) { JsonSchemaModel jsonSchemaModel = new JsonSchemaModel(); foreach (JsonSchema schematum in schemata) { Combine(jsonSchemaModel, schematum); } return jsonSchemaModel; } private static void Combine(JsonSchemaModel model, JsonSchema schema) { model.Required = model.Required || schema.Required.GetValueOrDefault(); model.Type &= schema.Type ?? JsonSchemaType.Any; model.MinimumLength = MathUtils.Max(model.MinimumLength, schema.MinimumLength); model.MaximumLength = MathUtils.Min(model.MaximumLength, schema.MaximumLength); model.DivisibleBy = MathUtils.Max(model.DivisibleBy, schema.DivisibleBy); model.Minimum = MathUtils.Max(model.Minimum, schema.Minimum); model.Maximum = MathUtils.Max(model.Maximum, schema.Maximum); model.ExclusiveMinimum = model.ExclusiveMinimum || schema.ExclusiveMinimum.GetValueOrDefault(); model.ExclusiveMaximum = model.ExclusiveMaximum || schema.ExclusiveMaximum.GetValueOrDefault(); model.MinimumItems = MathUtils.Max(model.MinimumItems, schema.MinimumItems); model.MaximumItems = MathUtils.Min(model.MaximumItems, schema.MaximumItems); model.PositionalItemsValidation = model.PositionalItemsValidation || schema.PositionalItemsValidation; model.AllowAdditionalProperties = model.AllowAdditionalProperties && schema.AllowAdditionalProperties; model.AllowAdditionalItems = model.AllowAdditionalItems && schema.AllowAdditionalItems; model.UniqueItems = model.UniqueItems || schema.UniqueItems; if (schema.Enum != null) { if (model.Enum == null) { model.Enum = new List(); } model.Enum.AddRangeDistinct(schema.Enum, JToken.EqualityComparer); } model.Disallow |= schema.Disallow.GetValueOrDefault(); if (schema.Pattern != null) { if (model.Patterns == null) { model.Patterns = new List(); } model.Patterns.AddDistinct(schema.Pattern); } } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaModelBuilder { private JsonSchemaNodeCollection _nodes = new JsonSchemaNodeCollection(); private Dictionary _nodeModels = new Dictionary(); private JsonSchemaNode _node; public JsonSchemaModel Build(JsonSchema schema) { _nodes = new JsonSchemaNodeCollection(); _node = AddSchema(null, schema); _nodeModels = new Dictionary(); return BuildNodeModel(_node); } public JsonSchemaNode AddSchema(JsonSchemaNode existingNode, JsonSchema schema) { string id; if (existingNode != null) { if (existingNode.Schemas.Contains(schema)) { return existingNode; } id = JsonSchemaNode.GetId(existingNode.Schemas.Union(new JsonSchema[1] { schema })); } else { id = JsonSchemaNode.GetId(new JsonSchema[1] { schema }); } if (_nodes.Contains(id)) { return _nodes[id]; } JsonSchemaNode jsonSchemaNode = ((existingNode != null) ? existingNode.Combine(schema) : new JsonSchemaNode(schema)); _nodes.Add(jsonSchemaNode); AddProperties(schema.Properties, jsonSchemaNode.Properties); AddProperties(schema.PatternProperties, jsonSchemaNode.PatternProperties); if (schema.Items != null) { for (int i = 0; i < schema.Items.Count; i++) { AddItem(jsonSchemaNode, i, schema.Items[i]); } } if (schema.AdditionalItems != null) { AddAdditionalItems(jsonSchemaNode, schema.AdditionalItems); } if (schema.AdditionalProperties != null) { AddAdditionalProperties(jsonSchemaNode, schema.AdditionalProperties); } if (schema.Extends != null) { foreach (JsonSchema extend in schema.Extends) { jsonSchemaNode = AddSchema(jsonSchemaNode, extend); } } return jsonSchemaNode; } public void AddProperties(IDictionary source, IDictionary target) { if (source == null) { return; } foreach (KeyValuePair item in source) { AddProperty(target, item.Key, item.Value); } } public void AddProperty(IDictionary target, string propertyName, JsonSchema schema) { target.TryGetValue(propertyName, out var value); target[propertyName] = AddSchema(value, schema); } public void AddItem(JsonSchemaNode parentNode, int index, JsonSchema schema) { JsonSchemaNode existingNode = ((parentNode.Items.Count > index) ? parentNode.Items[index] : null); JsonSchemaNode jsonSchemaNode = AddSchema(existingNode, schema); if (parentNode.Items.Count <= index) { parentNode.Items.Add(jsonSchemaNode); } else { parentNode.Items[index] = jsonSchemaNode; } } public void AddAdditionalProperties(JsonSchemaNode parentNode, JsonSchema schema) { parentNode.AdditionalProperties = AddSchema(parentNode.AdditionalProperties, schema); } public void AddAdditionalItems(JsonSchemaNode parentNode, JsonSchema schema) { parentNode.AdditionalItems = AddSchema(parentNode.AdditionalItems, schema); } private JsonSchemaModel BuildNodeModel(JsonSchemaNode node) { if (_nodeModels.TryGetValue(node, out var value)) { return value; } value = JsonSchemaModel.Create(node.Schemas); _nodeModels[node] = value; foreach (KeyValuePair property in node.Properties) { if (value.Properties == null) { value.Properties = new Dictionary(); } value.Properties[property.Key] = BuildNodeModel(property.Value); } foreach (KeyValuePair patternProperty in node.PatternProperties) { if (value.PatternProperties == null) { value.PatternProperties = new Dictionary(); } value.PatternProperties[patternProperty.Key] = BuildNodeModel(patternProperty.Value); } foreach (JsonSchemaNode item in node.Items) { if (value.Items == null) { value.Items = new List(); } value.Items.Add(BuildNodeModel(item)); } if (node.AdditionalProperties != null) { value.AdditionalProperties = BuildNodeModel(node.AdditionalProperties); } if (node.AdditionalItems != null) { value.AdditionalItems = BuildNodeModel(node.AdditionalItems); } return value; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaNode { public string Id { get; } public ReadOnlyCollection Schemas { get; } public Dictionary Properties { get; } public Dictionary PatternProperties { get; } public List Items { get; } public JsonSchemaNode AdditionalProperties { get; set; } public JsonSchemaNode AdditionalItems { get; set; } public JsonSchemaNode(JsonSchema schema) { Schemas = new ReadOnlyCollection(new JsonSchema[1] { schema }); Properties = new Dictionary(); PatternProperties = new Dictionary(); Items = new List(); Id = GetId(Schemas); } private JsonSchemaNode(JsonSchemaNode source, JsonSchema schema) { Schemas = new ReadOnlyCollection(source.Schemas.Union(new JsonSchema[1] { schema }).ToList()); Properties = new Dictionary(source.Properties); PatternProperties = new Dictionary(source.PatternProperties); Items = new List(source.Items); AdditionalProperties = source.AdditionalProperties; AdditionalItems = source.AdditionalItems; Id = GetId(Schemas); } public JsonSchemaNode Combine(JsonSchema schema) { return new JsonSchemaNode(this, schema); } public static string GetId(IEnumerable schemata) { return string.Join("-", schemata.Select((JsonSchema s) => s.InternalId).OrderBy((string id) => id, StringComparer.Ordinal)); } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaNodeCollection : KeyedCollection { protected override string GetKeyForItem(JsonSchemaNode item) { return item.Id; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaResolver { public IList LoadedSchemas { get; protected set; } public JsonSchemaResolver() { LoadedSchemas = new List(); } public virtual JsonSchema GetSchema(string reference) { JsonSchema jsonSchema = LoadedSchemas.SingleOrDefault((JsonSchema s) => string.Equals(s.Id, reference, StringComparison.Ordinal)); if (jsonSchema == null) { jsonSchema = LoadedSchemas.SingleOrDefault((JsonSchema s) => string.Equals(s.Location, reference, StringComparison.Ordinal)); } return jsonSchema; } } [Flags] [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal enum JsonSchemaType { None = 0, String = 1, Float = 2, Integer = 4, Boolean = 8, Object = 0x10, Array = 0x20, Null = 0x40, Any = 0x7F } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class JsonSchemaWriter { private readonly JsonWriter _writer; private readonly JsonSchemaResolver _resolver; public JsonSchemaWriter(JsonWriter writer, JsonSchemaResolver resolver) { ValidationUtils.ArgumentNotNull(writer, "writer"); _writer = writer; _resolver = resolver; } private void ReferenceOrWriteSchema(JsonSchema schema) { if (schema.Id != null && _resolver.GetSchema(schema.Id) != null) { _writer.WriteStartObject(); _writer.WritePropertyName("$ref"); _writer.WriteValue(schema.Id); _writer.WriteEndObject(); } else { WriteSchema(schema); } } public void WriteSchema(JsonSchema schema) { ValidationUtils.ArgumentNotNull(schema, "schema"); if (!_resolver.LoadedSchemas.Contains(schema)) { _resolver.LoadedSchemas.Add(schema); } _writer.WriteStartObject(); WritePropertyIfNotNull(_writer, "id", schema.Id); WritePropertyIfNotNull(_writer, "title", schema.Title); WritePropertyIfNotNull(_writer, "description", schema.Description); WritePropertyIfNotNull(_writer, "required", schema.Required); WritePropertyIfNotNull(_writer, "readonly", schema.ReadOnly); WritePropertyIfNotNull(_writer, "hidden", schema.Hidden); WritePropertyIfNotNull(_writer, "transient", schema.Transient); if (schema.Type.HasValue) { WriteType("type", _writer, schema.Type.GetValueOrDefault()); } if (!schema.AllowAdditionalProperties) { _writer.WritePropertyName("additionalProperties"); _writer.WriteValue(schema.AllowAdditionalProperties); } else if (schema.AdditionalProperties != null) { _writer.WritePropertyName("additionalProperties"); ReferenceOrWriteSchema(schema.AdditionalProperties); } if (!schema.AllowAdditionalItems) { _writer.WritePropertyName("additionalItems"); _writer.WriteValue(schema.AllowAdditionalItems); } else if (schema.AdditionalItems != null) { _writer.WritePropertyName("additionalItems"); ReferenceOrWriteSchema(schema.AdditionalItems); } WriteSchemaDictionaryIfNotNull(_writer, "properties", schema.Properties); WriteSchemaDictionaryIfNotNull(_writer, "patternProperties", schema.PatternProperties); WriteItems(schema); WritePropertyIfNotNull(_writer, "minimum", schema.Minimum); WritePropertyIfNotNull(_writer, "maximum", schema.Maximum); WritePropertyIfNotNull(_writer, "exclusiveMinimum", schema.ExclusiveMinimum); WritePropertyIfNotNull(_writer, "exclusiveMaximum", schema.ExclusiveMaximum); WritePropertyIfNotNull(_writer, "minLength", schema.MinimumLength); WritePropertyIfNotNull(_writer, "maxLength", schema.MaximumLength); WritePropertyIfNotNull(_writer, "minItems", schema.MinimumItems); WritePropertyIfNotNull(_writer, "maxItems", schema.MaximumItems); WritePropertyIfNotNull(_writer, "divisibleBy", schema.DivisibleBy); WritePropertyIfNotNull(_writer, "format", schema.Format); WritePropertyIfNotNull(_writer, "pattern", schema.Pattern); if (schema.Enum != null) { _writer.WritePropertyName("enum"); _writer.WriteStartArray(); foreach (JToken item in schema.Enum) { item.WriteTo(_writer); } _writer.WriteEndArray(); } if (schema.Default != null) { _writer.WritePropertyName("default"); schema.Default.WriteTo(_writer); } if (schema.Disallow.HasValue) { WriteType("disallow", _writer, schema.Disallow.GetValueOrDefault()); } if (schema.Extends != null && schema.Extends.Count > 0) { _writer.WritePropertyName("extends"); if (schema.Extends.Count == 1) { ReferenceOrWriteSchema(schema.Extends[0]); } else { _writer.WriteStartArray(); foreach (JsonSchema extend in schema.Extends) { ReferenceOrWriteSchema(extend); } _writer.WriteEndArray(); } } _writer.WriteEndObject(); } private void WriteSchemaDictionaryIfNotNull(JsonWriter writer, string propertyName, IDictionary properties) { if (properties == null) { return; } writer.WritePropertyName(propertyName); writer.WriteStartObject(); foreach (KeyValuePair property in properties) { writer.WritePropertyName(property.Key); ReferenceOrWriteSchema(property.Value); } writer.WriteEndObject(); } private void WriteItems(JsonSchema schema) { if (schema.Items == null && !schema.PositionalItemsValidation) { return; } _writer.WritePropertyName("items"); if (!schema.PositionalItemsValidation) { if (schema.Items != null && schema.Items.Count > 0) { ReferenceOrWriteSchema(schema.Items[0]); return; } _writer.WriteStartObject(); _writer.WriteEndObject(); return; } _writer.WriteStartArray(); if (schema.Items != null) { foreach (JsonSchema item in schema.Items) { ReferenceOrWriteSchema(item); } } _writer.WriteEndArray(); } private void WriteType(string propertyName, JsonWriter writer, JsonSchemaType type) { if (Enum.IsDefined(typeof(JsonSchemaType), type)) { writer.WritePropertyName(propertyName); writer.WriteValue(JsonSchemaBuilder.MapType(type)); return; } IEnumerator enumerator = (from v in EnumUtils.GetFlagsValues(type) where v != JsonSchemaType.None select v).GetEnumerator(); if (!enumerator.MoveNext()) { return; } writer.WritePropertyName(propertyName); JsonSchemaType current = enumerator.Current; if (enumerator.MoveNext()) { writer.WriteStartArray(); writer.WriteValue(JsonSchemaBuilder.MapType(current)); do { writer.WriteValue(JsonSchemaBuilder.MapType(enumerator.Current)); } while (enumerator.MoveNext()); writer.WriteEndArray(); } else { writer.WriteValue(JsonSchemaBuilder.MapType(current)); } } private void WritePropertyIfNotNull(JsonWriter writer, string propertyName, object value) { if (value != null) { writer.WritePropertyName(propertyName); writer.WriteValue(value); } } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal enum UndefinedSchemaIdHandling { None, UseTypeName, UseAssemblyQualifiedName } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal class ValidationEventArgs : EventArgs { private readonly JsonSchemaException _ex; public JsonSchemaException Exception => _ex; public string Path => _ex.Path; public string Message => _ex.Message; internal ValidationEventArgs(JsonSchemaException ex) { ValidationUtils.ArgumentNotNull(ex, "ex"); _ex = ex; } } [Obsolete("JSON Schema validation has been moved to its own package. See https://www.newtonsoft.com/jsonschema for more details.")] internal delegate void ValidationEventHandler(object sender, ValidationEventArgs e); } namespace Newtonsoft.Json.Linq { internal enum CommentHandling { Ignore, Load } internal enum DuplicatePropertyNameHandling { Replace, Ignore, Error } internal static class Extensions { public static IJEnumerable Ancestors(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T j) => j.Ancestors()).AsJEnumerable(); } public static IJEnumerable AncestorsAndSelf(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T j) => j.AncestorsAndSelf()).AsJEnumerable(); } public static IJEnumerable Descendants(this IEnumerable source) where T : JContainer { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T j) => j.Descendants()).AsJEnumerable(); } public static IJEnumerable DescendantsAndSelf(this IEnumerable source) where T : JContainer { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T j) => j.DescendantsAndSelf()).AsJEnumerable(); } public static IJEnumerable Properties(this IEnumerable source) { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((JObject d) => d.Properties()).AsJEnumerable(); } public static IJEnumerable Values(this IEnumerable source, object? key) { return source.Values(key).AsJEnumerable(); } public static IJEnumerable Values(this IEnumerable source) { return source.Values(null); } public static IEnumerable Values(this IEnumerable source, object key) { return source.Values(key); } public static IEnumerable Values(this IEnumerable source) { return source.Values(null); } public static U? Value(this IEnumerable value) { return value.Value(); } public static U? Value(this IEnumerable value) where T : JToken { ValidationUtils.ArgumentNotNull(value, "value"); return ((value as JToken) ?? throw new ArgumentException("Source value must be a JToken.")).Convert(); } internal static IEnumerable Values(this IEnumerable source, object? key) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); if (key == null) { foreach (T item in source) { if (item is JValue token) { yield return token.Convert(); continue; } foreach (JToken item2 in item.Children()) { yield return item2.Convert(); } } yield break; } foreach (T item3 in source) { JToken jToken = item3[key]; if (jToken != null) { yield return jToken.Convert(); } } } public static IJEnumerable Children(this IEnumerable source) where T : JToken { return source.Children().AsJEnumerable(); } public static IEnumerable Children(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); return source.SelectMany((T c) => c.Children()).Convert(); } internal static IEnumerable Convert(this IEnumerable source) where T : JToken { ValidationUtils.ArgumentNotNull(source, "source"); foreach (T item in source) { yield return item.Convert(); } } internal static U? Convert(this T token) where T : JToken? { if (token == null) { return default(U); } if (token is U) { U result = (U)(object)((token is U) ? token : null); if (typeof(U) != typeof(IComparable) && typeof(U) != typeof(IFormattable)) { return result; } } if (!(token is JValue jValue)) { throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(T))); } object value = jValue.Value; if (value is U) { return (U)value; } Type type = typeof(U); if (ReflectionUtils.IsNullableType(type)) { if (jValue.Value == null) { return default(U); } type = Nullable.GetUnderlyingType(type); } return (U)System.Convert.ChangeType(jValue.Value, type, CultureInfo.InvariantCulture); } public static IJEnumerable AsJEnumerable(this IEnumerable source) { return source.AsJEnumerable(); } public static IJEnumerable AsJEnumerable(this IEnumerable source) where T : JToken { if (source == null) { return null; } if (source is IJEnumerable result) { return result; } return new JEnumerable(source); } } internal interface IJEnumerable : IEnumerable, IEnumerable where T : JToken { IJEnumerable this[object key] { get; } } internal class JArray : JContainer, IList, ICollection, IEnumerable, IEnumerable { private readonly List _values = new List(); protected override IList ChildrenTokens => _values; public override JTokenType Type => JTokenType.Array; public override JToken? this[object key] { get { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is int)) { throw new ArgumentException("Accessed JArray values with invalid key value: {0}. Int32 array index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } return GetItem((int)key); } set { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is int)) { throw new ArgumentException("Set JArray values with invalid key value: {0}. Int32 array index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } SetItem((int)key, value); } } public JToken this[int index] { get { return GetItem(index); } set { SetItem(index, value); } } public bool IsReadOnly => false; public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { await writer.WriteStartArrayAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); for (int i = 0; i < _values.Count; i++) { await _values[i].WriteToAsync(writer, cancellationToken, converters).ConfigureAwait(continueOnCapturedContext: false); } await writer.WriteEndArrayAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { if (reader.TokenType == JsonToken.None && !(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader."); } await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.TokenType != JsonToken.StartArray) { throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JArray a = new JArray(); a.SetLineInfo(reader as IJsonLineInfo, settings); await a.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return a; } public JArray() { } public JArray(JArray other) : base(other, null) { } internal JArray(JArray other, JsonCloneSettings? settings) : base(other, settings) { } public JArray(params object[] content) : this((object)content) { } public JArray(object content) { Add(content); } internal override bool DeepEquals(JToken node) { if (node is JArray container) { return ContentsEqual(container); } return false; } internal override JToken CloneToken(JsonCloneSettings? settings = null) { return new JArray(this, settings); } public new static JArray Load(JsonReader reader) { return Load(reader, null); } public new static JArray Load(JsonReader reader, JsonLoadSettings? settings) { if (reader.TokenType == JsonToken.None && !reader.Read()) { throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader."); } reader.MoveToContent(); if (reader.TokenType != JsonToken.StartArray) { throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JArray jArray = new JArray(); jArray.SetLineInfo(reader as IJsonLineInfo, settings); jArray.ReadTokenFrom(reader, settings); return jArray; } public new static JArray Parse(string json) { return Parse(json, null); } public new static JArray Parse(string json, JsonLoadSettings? settings) { using JsonReader jsonReader = new JsonTextReader(new StringReader(json)); JArray result = Load(jsonReader, settings); while (jsonReader.Read()) { } return result; } public new static JArray FromObject(object o) { return FromObject(o, JsonSerializer.CreateDefault()); } public new static JArray FromObject(object o, JsonSerializer jsonSerializer) { JToken jToken = JToken.FromObjectInternal(o, jsonSerializer); if (jToken.Type != JTokenType.Array) { throw new ArgumentException("Object serialized to {0}. JArray instance expected.".FormatWith(CultureInfo.InvariantCulture, jToken.Type)); } return (JArray)jToken; } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { writer.WriteStartArray(); for (int i = 0; i < _values.Count; i++) { _values[i].WriteTo(writer, converters); } writer.WriteEndArray(); } internal override int IndexOfItem(JToken? item) { if (item == null) { return -1; } return _values.IndexOfReference(item); } internal override void MergeItem(object content, JsonMergeSettings? settings) { IEnumerable enumerable = ((IsMultiContent(content) || content is JArray) ? ((IEnumerable)content) : null); if (enumerable != null) { JContainer.MergeEnumerableContent(this, enumerable, settings); } } public int IndexOf(JToken item) { return IndexOfItem(item); } public void Insert(int index, JToken item) { InsertItem(index, item, skipParentCheck: false, copyAnnotations: true); } public void RemoveAt(int index) { RemoveItemAt(index); } public IEnumerator GetEnumerator() { return Children().GetEnumerator(); } public void Add(JToken item) { Add((object?)item); } public void Clear() { ClearItems(); } public bool Contains(JToken item) { return ContainsItem(item); } public void CopyTo(JToken[] array, int arrayIndex) { CopyItemsTo(array, arrayIndex); } public bool Remove(JToken item) { return RemoveItem(item); } internal override int GetDeepHashCode() { return ContentsHashCode(); } } internal class JConstructor : JContainer { private string? _name; private readonly List _values = new List(); protected override IList ChildrenTokens => _values; public string? Name { get { return _name; } set { _name = value; } } public override JTokenType Type => JTokenType.Constructor; public override JToken? this[object key] { get { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is int index)) { throw new ArgumentException("Accessed JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } return GetItem(index); } set { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is int index)) { throw new ArgumentException("Set JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } SetItem(index, value); } } public override async Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { await writer.WriteStartConstructorAsync(_name ?? string.Empty, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); for (int i = 0; i < _values.Count; i++) { await _values[i].WriteToAsync(writer, cancellationToken, converters).ConfigureAwait(continueOnCapturedContext: false); } await writer.WriteEndConstructorAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { if (reader.TokenType == JsonToken.None && !(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader."); } await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.TokenType != JsonToken.StartConstructor) { throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JConstructor c = new JConstructor((string)reader.Value); c.SetLineInfo(reader as IJsonLineInfo, settings); await c.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return c; } internal override int IndexOfItem(JToken? item) { if (item == null) { return -1; } return _values.IndexOfReference(item); } internal override void MergeItem(object content, JsonMergeSettings? settings) { if (content is JConstructor jConstructor) { if (jConstructor.Name != null) { Name = jConstructor.Name; } JContainer.MergeEnumerableContent(this, jConstructor, settings); } } public JConstructor() { } public JConstructor(JConstructor other) : base(other, null) { _name = other.Name; } internal JConstructor(JConstructor other, JsonCloneSettings? settings) : base(other, settings) { _name = other.Name; } public JConstructor(string name, params object[] content) : this(name, (object)content) { } public JConstructor(string name, object content) : this(name) { Add(content); } public JConstructor(string name) { if (name == null) { throw new ArgumentNullException("name"); } if (name.Length == 0) { throw new ArgumentException("Constructor name cannot be empty.", "name"); } _name = name; } internal override bool DeepEquals(JToken node) { if (node is JConstructor jConstructor && _name == jConstructor.Name) { return ContentsEqual(jConstructor); } return false; } internal override JToken CloneToken(JsonCloneSettings? settings = null) { return new JConstructor(this, settings); } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { writer.WriteStartConstructor(_name); int count = _values.Count; for (int i = 0; i < count; i++) { _values[i].WriteTo(writer, converters); } writer.WriteEndConstructor(); } internal override int GetDeepHashCode() { return (_name?.GetHashCode() ?? 0) ^ ContentsHashCode(); } public new static JConstructor Load(JsonReader reader) { return Load(reader, null); } public new static JConstructor Load(JsonReader reader, JsonLoadSettings? settings) { if (reader.TokenType == JsonToken.None && !reader.Read()) { throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader."); } reader.MoveToContent(); if (reader.TokenType != JsonToken.StartConstructor) { throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JConstructor jConstructor = new JConstructor((string)reader.Value); jConstructor.SetLineInfo(reader as IJsonLineInfo, settings); jConstructor.ReadTokenFrom(reader, settings); return jConstructor; } } internal abstract class JContainer : JToken, IList, ICollection, IEnumerable, IEnumerable, ITypedList, IBindingList, IList, ICollection, INotifyCollectionChanged { internal ListChangedEventHandler? _listChanged; internal AddingNewEventHandler? _addingNew; internal NotifyCollectionChangedEventHandler? _collectionChanged; private object? _syncRoot; private bool _busy; protected abstract IList ChildrenTokens { get; } public override bool HasValues => ChildrenTokens.Count > 0; public override JToken? First { get { IList childrenTokens = ChildrenTokens; if (childrenTokens.Count <= 0) { return null; } return childrenTokens[0]; } } public override JToken? Last { get { IList childrenTokens = ChildrenTokens; int count = childrenTokens.Count; if (count <= 0) { return null; } return childrenTokens[count - 1]; } } JToken IList.this[int index] { get { return GetItem(index); } set { SetItem(index, value); } } bool ICollection.IsReadOnly => false; bool IList.IsFixedSize => false; bool IList.IsReadOnly => false; object? IList.this[int index] { get { return GetItem(index); } set { SetItem(index, EnsureValue(value)); } } public int Count => ChildrenTokens.Count; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot { get { if (_syncRoot == null) { Interlocked.CompareExchange(ref _syncRoot, new object(), null); } return _syncRoot; } } bool IBindingList.AllowEdit => true; bool IBindingList.AllowNew => true; bool IBindingList.AllowRemove => true; bool IBindingList.IsSorted => false; ListSortDirection IBindingList.SortDirection => ListSortDirection.Ascending; PropertyDescriptor? IBindingList.SortProperty => null; bool IBindingList.SupportsChangeNotification => true; bool IBindingList.SupportsSearching => false; bool IBindingList.SupportsSorting => false; public event ListChangedEventHandler ListChanged { add { _listChanged = (ListChangedEventHandler)Delegate.Combine(_listChanged, value); } remove { _listChanged = (ListChangedEventHandler)Delegate.Remove(_listChanged, value); } } public event AddingNewEventHandler AddingNew { add { _addingNew = (AddingNewEventHandler)Delegate.Combine(_addingNew, value); } remove { _addingNew = (AddingNewEventHandler)Delegate.Remove(_addingNew, value); } } public event NotifyCollectionChangedEventHandler? CollectionChanged { add { _collectionChanged = (NotifyCollectionChangedEventHandler)Delegate.Combine(_collectionChanged, value); } remove { _collectionChanged = (NotifyCollectionChangedEventHandler)Delegate.Remove(_collectionChanged, value); } } internal async Task ReadTokenFromAsync(JsonReader reader, JsonLoadSettings? options, CancellationToken cancellationToken = default(CancellationToken)) { ValidationUtils.ArgumentNotNull(reader, "reader"); int startDepth = reader.Depth; if (!(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); } await ReadContentFromAsync(reader, options, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.Depth > startDepth) { throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); } } private async Task ReadContentFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { IJsonLineInfo lineInfo = reader as IJsonLineInfo; JContainer parent = this; do { if (parent is JProperty jProperty && jProperty.Value != null) { if (parent == this) { break; } parent = parent.Parent; } switch (reader.TokenType) { case JsonToken.StartArray: { JArray jArray = new JArray(); jArray.SetLineInfo(lineInfo, settings); parent.Add(jArray); parent = jArray; break; } case JsonToken.EndArray: if (parent == this) { return; } parent = parent.Parent; break; case JsonToken.StartObject: { JObject jObject = new JObject(); jObject.SetLineInfo(lineInfo, settings); parent.Add(jObject); parent = jObject; break; } case JsonToken.EndObject: if (parent == this) { return; } parent = parent.Parent; break; case JsonToken.StartConstructor: { JConstructor jConstructor = new JConstructor(reader.Value.ToString()); jConstructor.SetLineInfo(lineInfo, settings); parent.Add(jConstructor); parent = jConstructor; break; } case JsonToken.EndConstructor: if (parent == this) { return; } parent = parent.Parent; break; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { JValue jValue = new JValue(reader.Value); jValue.SetLineInfo(lineInfo, settings); parent.Add(jValue); break; } case JsonToken.Comment: if (settings != null && settings.CommentHandling == CommentHandling.Load) { JValue jValue = JValue.CreateComment(reader.Value.ToString()); jValue.SetLineInfo(lineInfo, settings); parent.Add(jValue); } break; case JsonToken.Null: { JValue jValue = JValue.CreateNull(); jValue.SetLineInfo(lineInfo, settings); parent.Add(jValue); break; } case JsonToken.Undefined: { JValue jValue = JValue.CreateUndefined(); jValue.SetLineInfo(lineInfo, settings); parent.Add(jValue); break; } case JsonToken.PropertyName: { JProperty jProperty2 = ReadProperty(reader, settings, lineInfo, parent); if (jProperty2 != null) { parent = jProperty2; } else { await reader.SkipAsync().ConfigureAwait(continueOnCapturedContext: false); } break; } default: throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); case JsonToken.None: break; } } while (await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false)); } internal JContainer() { } internal JContainer(JContainer other, JsonCloneSettings? settings) : this() { ValidationUtils.ArgumentNotNull(other, "other"); bool flag = settings?.CopyAnnotations ?? true; if (flag) { CopyAnnotations(this, other); } int num = 0; foreach (JToken item in (IEnumerable)other) { TryAddInternal(num, item, skipParentCheck: false, flag); num++; } } internal void CheckReentrancy() { if (_busy) { throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType())); } } internal virtual IList CreateChildrenCollection() { return new List(); } protected virtual void OnAddingNew(AddingNewEventArgs e) { _addingNew?.Invoke(this, e); } protected virtual void OnListChanged(ListChangedEventArgs e) { ListChangedEventHandler listChanged = _listChanged; if (listChanged != null) { _busy = true; try { listChanged(this, e); } finally { _busy = false; } } } protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { NotifyCollectionChangedEventHandler collectionChanged = _collectionChanged; if (collectionChanged != null) { _busy = true; try { collectionChanged(this, e); } finally { _busy = false; } } } internal bool ContentsEqual(JContainer container) { if (container == this) { return true; } IList childrenTokens = ChildrenTokens; IList childrenTokens2 = container.ChildrenTokens; if (childrenTokens.Count != childrenTokens2.Count) { return false; } for (int i = 0; i < childrenTokens.Count; i++) { if (!childrenTokens[i].DeepEquals(childrenTokens2[i])) { return false; } } return true; } public override JEnumerable Children() { return new JEnumerable(ChildrenTokens); } public override IEnumerable Values() { return ChildrenTokens.Convert(); } public IEnumerable Descendants() { return GetDescendants(self: false); } public IEnumerable DescendantsAndSelf() { return GetDescendants(self: true); } internal IEnumerable GetDescendants(bool self) { if (self) { yield return this; } foreach (JToken o in ChildrenTokens) { yield return o; if (!(o is JContainer jContainer)) { continue; } foreach (JToken item in jContainer.Descendants()) { yield return item; } } } internal bool IsMultiContent([NotNullWhen(true)] object? content) { if (content is IEnumerable && !(content is string) && !(content is JToken)) { return !(content is byte[]); } return false; } internal JToken EnsureParentToken(JToken? item, bool skipParentCheck, bool copyAnnotations) { if (item == null) { return JValue.CreateNull(); } if (skipParentCheck) { return item; } if (item.Parent != null || item == this || (item.HasValues && base.Root == item)) { JsonCloneSettings settings = (copyAnnotations ? null : JsonCloneSettings.SkipCopyAnnotations); item = item.CloneToken(settings); } return item; } internal abstract int IndexOfItem(JToken? item); internal virtual bool InsertItem(int index, JToken? item, bool skipParentCheck, bool copyAnnotations) { IList childrenTokens = ChildrenTokens; if (index > childrenTokens.Count) { throw new ArgumentOutOfRangeException("index", "Index must be within the bounds of the List."); } CheckReentrancy(); item = EnsureParentToken(item, skipParentCheck, copyAnnotations); JToken jToken = ((index == 0) ? null : childrenTokens[index - 1]); JToken jToken2 = ((index == childrenTokens.Count) ? null : childrenTokens[index]); ValidateToken(item, null); item.Parent = this; item.Previous = jToken; if (jToken != null) { jToken.Next = item; } item.Next = jToken2; if (jToken2 != null) { jToken2.Previous = item; } childrenTokens.Insert(index, item); if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index)); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index)); } return true; } internal virtual void RemoveItemAt(int index) { IList childrenTokens = ChildrenTokens; if (index < 0) { throw new ArgumentOutOfRangeException("index", "Index is less than 0."); } if (index >= childrenTokens.Count) { throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count."); } CheckReentrancy(); JToken jToken = childrenTokens[index]; JToken jToken2 = ((index == 0) ? null : childrenTokens[index - 1]); JToken jToken3 = ((index == childrenTokens.Count - 1) ? null : childrenTokens[index + 1]); if (jToken2 != null) { jToken2.Next = jToken3; } if (jToken3 != null) { jToken3.Previous = jToken2; } jToken.Parent = null; jToken.Previous = null; jToken.Next = null; childrenTokens.RemoveAt(index); if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index)); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, jToken, index)); } } internal virtual bool RemoveItem(JToken? item) { if (item != null) { int num = IndexOfItem(item); if (num >= 0) { RemoveItemAt(num); return true; } } return false; } internal virtual JToken GetItem(int index) { return ChildrenTokens[index]; } internal virtual void SetItem(int index, JToken? item) { IList childrenTokens = ChildrenTokens; if (index < 0) { throw new ArgumentOutOfRangeException("index", "Index is less than 0."); } if (index >= childrenTokens.Count) { throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count."); } JToken jToken = childrenTokens[index]; if (!IsTokenUnchanged(jToken, item)) { CheckReentrancy(); item = EnsureParentToken(item, skipParentCheck: false, copyAnnotations: true); ValidateToken(item, jToken); JToken jToken2 = ((index == 0) ? null : childrenTokens[index - 1]); JToken jToken3 = ((index == childrenTokens.Count - 1) ? null : childrenTokens[index + 1]); item.Parent = this; item.Previous = jToken2; if (jToken2 != null) { jToken2.Next = item; } item.Next = jToken3; if (jToken3 != null) { jToken3.Previous = item; } childrenTokens[index] = item; jToken.Parent = null; jToken.Previous = null; jToken.Next = null; if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index)); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, jToken, index)); } } } internal virtual void ClearItems() { CheckReentrancy(); IList childrenTokens = ChildrenTokens; foreach (JToken item in childrenTokens) { item.Parent = null; item.Previous = null; item.Next = null; } childrenTokens.Clear(); if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1)); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } } internal virtual void ReplaceItem(JToken existing, JToken replacement) { if (existing != null && existing.Parent == this) { int index = IndexOfItem(existing); SetItem(index, replacement); } } internal virtual bool ContainsItem(JToken? item) { return IndexOfItem(item) != -1; } internal virtual void CopyItemsTo(Array array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0) { throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0."); } if (arrayIndex >= array.Length && arrayIndex != 0) { throw new ArgumentException("arrayIndex is equal to or greater than the length of array."); } if (Count > array.Length - arrayIndex) { throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array."); } int num = 0; foreach (JToken childrenToken in ChildrenTokens) { array.SetValue(childrenToken, arrayIndex + num); num++; } } internal static bool IsTokenUnchanged(JToken currentValue, JToken? newValue) { if (currentValue is JValue jValue) { if (newValue == null) { return jValue.Type == JTokenType.Null; } return jValue.Equals(newValue); } return false; } internal virtual void ValidateToken(JToken o, JToken? existing) { ValidationUtils.ArgumentNotNull(o, "o"); if (o.Type == JTokenType.Property) { throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType())); } } public virtual void Add(object? content) { TryAddInternal(ChildrenTokens.Count, content, skipParentCheck: false, copyAnnotations: true); } internal bool TryAdd(object? content) { return TryAddInternal(ChildrenTokens.Count, content, skipParentCheck: false, copyAnnotations: true); } internal void AddAndSkipParentCheck(JToken token) { TryAddInternal(ChildrenTokens.Count, token, skipParentCheck: true, copyAnnotations: true); } public void AddFirst(object? content) { TryAddInternal(0, content, skipParentCheck: false, copyAnnotations: true); } internal bool TryAddInternal(int index, object? content, bool skipParentCheck, bool copyAnnotations) { if (IsMultiContent(content)) { IEnumerable obj = (IEnumerable)content; int num = index; foreach (object item2 in obj) { TryAddInternal(num, item2, skipParentCheck, copyAnnotations); num++; } return true; } JToken item = CreateFromContent(content); return InsertItem(index, item, skipParentCheck, copyAnnotations); } internal static JToken CreateFromContent(object? content) { if (content is JToken result) { return result; } return new JValue(content); } public JsonWriter CreateWriter() { return new JTokenWriter(this); } public void ReplaceAll(object content) { ClearItems(); Add(content); } public void RemoveAll() { ClearItems(); } internal abstract void MergeItem(object content, JsonMergeSettings? settings); public void Merge(object? content) { if (content != null) { ValidateContent(content); MergeItem(content, null); } } public void Merge(object? content, JsonMergeSettings? settings) { if (content != null) { ValidateContent(content); MergeItem(content, settings); } } private void ValidateContent(object content) { if (content.GetType().IsSubclassOf(typeof(JToken)) || IsMultiContent(content)) { return; } throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, content.GetType()), "content"); } internal void ReadTokenFrom(JsonReader reader, JsonLoadSettings? options) { int depth = reader.Depth; if (!reader.Read()) { throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); } ReadContentFrom(reader, options); if (reader.Depth > depth) { throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name)); } } internal void ReadContentFrom(JsonReader r, JsonLoadSettings? settings) { ValidationUtils.ArgumentNotNull(r, "r"); IJsonLineInfo lineInfo = r as IJsonLineInfo; JContainer jContainer = this; do { if (jContainer is JProperty jProperty && jProperty.Value != null) { if (jContainer == this) { break; } jContainer = jContainer.Parent; } switch (r.TokenType) { case JsonToken.StartArray: { JArray jArray = new JArray(); jArray.SetLineInfo(lineInfo, settings); jContainer.Add(jArray); jContainer = jArray; break; } case JsonToken.EndArray: if (jContainer == this) { return; } jContainer = jContainer.Parent; break; case JsonToken.StartObject: { JObject jObject = new JObject(); jObject.SetLineInfo(lineInfo, settings); jContainer.Add(jObject); jContainer = jObject; break; } case JsonToken.EndObject: if (jContainer == this) { return; } jContainer = jContainer.Parent; break; case JsonToken.StartConstructor: { JConstructor jConstructor = new JConstructor(r.Value.ToString()); jConstructor.SetLineInfo(lineInfo, settings); jContainer.Add(jConstructor); jContainer = jConstructor; break; } case JsonToken.EndConstructor: if (jContainer == this) { return; } jContainer = jContainer.Parent; break; case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { JValue jValue = new JValue(r.Value); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); break; } case JsonToken.Comment: if (settings != null && settings.CommentHandling == CommentHandling.Load) { JValue jValue = JValue.CreateComment(r.Value.ToString()); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); } break; case JsonToken.Null: { JValue jValue = JValue.CreateNull(); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); break; } case JsonToken.Undefined: { JValue jValue = JValue.CreateUndefined(); jValue.SetLineInfo(lineInfo, settings); jContainer.Add(jValue); break; } case JsonToken.PropertyName: { JProperty jProperty2 = ReadProperty(r, settings, lineInfo, jContainer); if (jProperty2 != null) { jContainer = jProperty2; } else { r.Skip(); } break; } default: throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, r.TokenType)); case JsonToken.None: break; } } while (r.Read()); } private static JProperty? ReadProperty(JsonReader r, JsonLoadSettings? settings, IJsonLineInfo? lineInfo, JContainer parent) { DuplicatePropertyNameHandling duplicatePropertyNameHandling = settings?.DuplicatePropertyNameHandling ?? DuplicatePropertyNameHandling.Replace; JObject obj = (JObject)parent; string text = r.Value.ToString(); JProperty jProperty = obj.Property(text, StringComparison.Ordinal); if (jProperty != null) { switch (duplicatePropertyNameHandling) { case DuplicatePropertyNameHandling.Ignore: return null; case DuplicatePropertyNameHandling.Error: throw JsonReaderException.Create(r, "Property with the name '{0}' already exists in the current JSON object.".FormatWith(CultureInfo.InvariantCulture, text)); } } JProperty jProperty2 = new JProperty(text); jProperty2.SetLineInfo(lineInfo, settings); if (jProperty == null) { parent.Add(jProperty2); } else { jProperty.Replace(jProperty2); } return jProperty2; } internal int ContentsHashCode() { int num = 0; foreach (JToken childrenToken in ChildrenTokens) { num ^= childrenToken.GetDeepHashCode(); } return num; } string ITypedList.GetListName(PropertyDescriptor[] listAccessors) { return string.Empty; } PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors) { return (First as ICustomTypeDescriptor)?.GetProperties() ?? new PropertyDescriptorCollection(CollectionUtils.ArrayEmpty()); } int IList.IndexOf(JToken item) { return IndexOfItem(item); } void IList.Insert(int index, JToken item) { InsertItem(index, item, skipParentCheck: false, copyAnnotations: true); } void IList.RemoveAt(int index) { RemoveItemAt(index); } void ICollection.Add(JToken item) { Add(item); } void ICollection.Clear() { ClearItems(); } bool ICollection.Contains(JToken item) { return ContainsItem(item); } void ICollection.CopyTo(JToken[] array, int arrayIndex) { CopyItemsTo(array, arrayIndex); } bool ICollection.Remove(JToken item) { return RemoveItem(item); } private JToken? EnsureValue(object? value) { if (value == null) { return null; } if (value is JToken result) { return result; } throw new ArgumentException("Argument is not a JToken."); } int IList.Add(object? value) { Add(EnsureValue(value)); return Count - 1; } void IList.Clear() { ClearItems(); } bool IList.Contains(object? value) { return ContainsItem(EnsureValue(value)); } int IList.IndexOf(object? value) { return IndexOfItem(EnsureValue(value)); } void IList.Insert(int index, object? value) { InsertItem(index, EnsureValue(value), skipParentCheck: false, copyAnnotations: false); } void IList.Remove(object? value) { RemoveItem(EnsureValue(value)); } void IList.RemoveAt(int index) { RemoveItemAt(index); } void ICollection.CopyTo(Array array, int index) { CopyItemsTo(array, index); } void IBindingList.AddIndex(PropertyDescriptor property) { } object IBindingList.AddNew() { AddingNewEventArgs addingNewEventArgs = new AddingNewEventArgs(); OnAddingNew(addingNewEventArgs); if (addingNewEventArgs.NewObject == null) { throw new JsonException("Could not determine new value to add to '{0}'.".FormatWith(CultureInfo.InvariantCulture, GetType())); } if (!(addingNewEventArgs.NewObject is JToken jToken)) { throw new JsonException("New item to be added to collection must be compatible with {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JToken))); } Add(jToken); return jToken; } void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction) { throw new NotSupportedException(); } int IBindingList.Find(PropertyDescriptor property, object key) { throw new NotSupportedException(); } void IBindingList.RemoveIndex(PropertyDescriptor property) { } void IBindingList.RemoveSort() { throw new NotSupportedException(); } internal static void MergeEnumerableContent(JContainer target, IEnumerable content, JsonMergeSettings? settings) { switch (settings?.MergeArrayHandling ?? MergeArrayHandling.Concat) { case MergeArrayHandling.Concat: { foreach (object item in content) { target.Add(CreateFromContent(item)); } break; } case MergeArrayHandling.Union: { HashSet hashSet = new HashSet(target, JToken.EqualityComparer); { foreach (object item2 in content) { JToken jToken2 = CreateFromContent(item2); if (hashSet.Add(jToken2)) { target.Add(jToken2); } } break; } } case MergeArrayHandling.Replace: if (target == content) { break; } target.ClearItems(); { foreach (object item3 in content) { target.Add(CreateFromContent(item3)); } break; } case MergeArrayHandling.Merge: { int num = 0; { foreach (object item4 in content) { if (num < target.Count) { if (target[num] is JContainer jContainer) { jContainer.Merge(item4, settings); } else if (item4 != null) { JToken jToken = CreateFromContent(item4); if (jToken.Type != JTokenType.Null) { target[num] = jToken; } } } else { target.Add(CreateFromContent(item4)); } num++; } break; } } default: throw new ArgumentOutOfRangeException("settings", "Unexpected merge array handling when merging JSON."); } } } internal readonly struct JEnumerable : IJEnumerable, IEnumerable, IEnumerable, IEquatable> where T : JToken { public static readonly JEnumerable Empty = new JEnumerable(Enumerable.Empty()); private readonly IEnumerable _enumerable; public IJEnumerable this[object key] { get { if (_enumerable == null) { return JEnumerable.Empty; } return new JEnumerable(_enumerable.Values(key)); } } public JEnumerable(IEnumerable enumerable) { ValidationUtils.ArgumentNotNull(enumerable, "enumerable"); _enumerable = enumerable; } public IEnumerator GetEnumerator() { return ((IEnumerable)(_enumerable ?? ((object)Empty))).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public bool Equals(JEnumerable other) { return object.Equals(_enumerable, other._enumerable); } public override bool Equals(object? obj) { if (obj is JEnumerable other) { return Equals(other); } return false; } public override int GetHashCode() { if (_enumerable == null) { return 0; } return _enumerable.GetHashCode(); } } internal class JObject : JContainer, IDictionary, ICollection>, IEnumerable>, IEnumerable, INotifyPropertyChanged, ICustomTypeDescriptor, INotifyPropertyChanging { private class JObjectDynamicProxy : DynamicProxy { public override bool TryGetMember(JObject instance, GetMemberBinder binder, out object? result) { result = instance[binder.Name]; return true; } public override bool TrySetMember(JObject instance, SetMemberBinder binder, object value) { JToken jToken = value as JToken; if (jToken == null) { jToken = new JValue(value); } instance[binder.Name] = jToken; return true; } public override IEnumerable GetDynamicMemberNames(JObject instance) { return from p in instance.Properties() select p.Name; } } private readonly JPropertyKeyedCollection _properties = new JPropertyKeyedCollection(); protected override IList ChildrenTokens => _properties; public override JTokenType Type => JTokenType.Object; public override JToken? this[object key] { get { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is string propertyName)) { throw new ArgumentException("Accessed JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } return this[propertyName]; } set { ValidationUtils.ArgumentNotNull(key, "key"); if (!(key is string propertyName)) { throw new ArgumentException("Set JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key))); } this[propertyName] = value; } } public JToken? this[string propertyName] { get { ValidationUtils.ArgumentNotNull(propertyName, "propertyName"); return Property(propertyName, StringComparison.Ordinal)?.Value; } set { JProperty jProperty = Property(propertyName, StringComparison.Ordinal); if (jProperty != null) { jProperty.Value = value; return; } OnPropertyChanging(propertyName); Add(propertyName, value); OnPropertyChanged(propertyName); } } ICollection IDictionary.Keys => _properties.Keys; ICollection IDictionary.Values { get { throw new NotImplementedException(); } } bool ICollection>.IsReadOnly => false; public event PropertyChangedEventHandler? PropertyChanged; public event PropertyChangingEventHandler? PropertyChanging; public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { Task task2 = writer.WriteStartObjectAsync(cancellationToken); if (!task2.IsCompletedSuccessfully()) { return AwaitProperties(task2, 0, writer, cancellationToken, converters); } for (int j = 0; j < _properties.Count; j++) { task2 = _properties[j].WriteToAsync(writer, cancellationToken, converters); if (!task2.IsCompletedSuccessfully()) { return AwaitProperties(task2, j + 1, writer, cancellationToken, converters); } } return writer.WriteEndObjectAsync(cancellationToken); async Task AwaitProperties(Task task, int i, JsonWriter Writer, CancellationToken CancellationToken, JsonConverter[] Converters) { await task.ConfigureAwait(continueOnCapturedContext: false); while (i < _properties.Count) { await _properties[i].WriteToAsync(Writer, CancellationToken, Converters).ConfigureAwait(continueOnCapturedContext: false); i++; } await Writer.WriteEndObjectAsync(CancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (reader.TokenType == JsonToken.None && !(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader."); } await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.TokenType != JsonToken.StartObject) { throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JObject o = new JObject(); o.SetLineInfo(reader as IJsonLineInfo, settings); await o.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return o; } public JObject() { } public JObject(JObject other) : base(other, null) { } internal JObject(JObject other, JsonCloneSettings? settings) : base(other, settings) { } public JObject(params object[] content) : this((object)content) { } public JObject(object content) { Add(content); } internal override bool DeepEquals(JToken node) { if (!(node is JObject jObject)) { return false; } return _properties.Compare(jObject._properties); } internal override int IndexOfItem(JToken? item) { if (item == null) { return -1; } return _properties.IndexOfReference(item); } internal override bool InsertItem(int index, JToken? item, bool skipParentCheck, bool copyAnnotations) { if (item != null && item.Type == JTokenType.Comment) { return false; } return base.InsertItem(index, item, skipParentCheck, copyAnnotations); } internal override void ValidateToken(JToken o, JToken? existing) { ValidationUtils.ArgumentNotNull(o, "o"); if (o.Type != JTokenType.Property) { throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType())); } JProperty jProperty = (JProperty)o; if (existing != null) { JProperty jProperty2 = (JProperty)existing; if (jProperty.Name == jProperty2.Name) { return; } } if (_properties.TryGetValue(jProperty.Name, out existing)) { throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, jProperty.Name, GetType())); } } internal override void MergeItem(object content, JsonMergeSettings? settings) { if (!(content is JObject jObject)) { return; } foreach (KeyValuePair item in jObject) { JProperty jProperty = Property(item.Key, settings?.PropertyNameComparison ?? StringComparison.Ordinal); if (jProperty == null) { Add(item.Key, item.Value); } else { if (item.Value == null) { continue; } if (!(jProperty.Value is JContainer jContainer) || jContainer.Type != item.Value.Type) { if (!IsNull(item.Value) || (settings != null && settings.MergeNullValueHandling == MergeNullValueHandling.Merge)) { jProperty.Value = item.Value; } } else { jContainer.Merge(item.Value, settings); } } } } private static bool IsNull(JToken token) { if (token.Type == JTokenType.Null) { return true; } if (token is JValue jValue && jValue.Value == null) { return true; } return false; } internal void InternalPropertyChanged(JProperty childProperty) { OnPropertyChanged(childProperty.Name); if (_listChanged != null) { OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, IndexOfItem(childProperty))); } if (_collectionChanged != null) { OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, childProperty, childProperty, IndexOfItem(childProperty))); } } internal void InternalPropertyChanging(JProperty childProperty) { OnPropertyChanging(childProperty.Name); } internal override JToken CloneToken(JsonCloneSettings? settings) { return new JObject(this, settings); } public IEnumerable Properties() { return _properties.Cast(); } public JProperty? Property(string name) { return Property(name, StringComparison.Ordinal); } public JProperty? Property(string name, StringComparison comparison) { if (name == null) { return null; } if (_properties.TryGetValue(name, out JToken value)) { return (JProperty)value; } if (comparison != StringComparison.Ordinal) { for (int i = 0; i < _properties.Count; i++) { JProperty jProperty = (JProperty)_properties[i]; if (string.Equals(jProperty.Name, name, comparison)) { return jProperty; } } } return null; } public JEnumerable PropertyValues() { return new JEnumerable(from p in Properties() select p.Value); } public new static JObject Load(JsonReader reader) { return Load(reader, null); } public new static JObject Load(JsonReader reader, JsonLoadSettings? settings) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (reader.TokenType == JsonToken.None && !reader.Read()) { throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader."); } reader.MoveToContent(); if (reader.TokenType != JsonToken.StartObject) { throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JObject jObject = new JObject(); jObject.SetLineInfo(reader as IJsonLineInfo, settings); jObject.ReadTokenFrom(reader, settings); return jObject; } public new static JObject Parse(string json) { return Parse(json, null); } public new static JObject Parse(string json, JsonLoadSettings? settings) { using JsonReader jsonReader = new JsonTextReader(new StringReader(json)); JObject result = Load(jsonReader, settings); while (jsonReader.Read()) { } return result; } public new static JObject FromObject(object o) { return FromObject(o, JsonSerializer.CreateDefault()); } public new static JObject FromObject(object o, JsonSerializer jsonSerializer) { JToken jToken = JToken.FromObjectInternal(o, jsonSerializer); if (jToken.Type != JTokenType.Object) { throw new ArgumentException("Object serialized to {0}. JObject instance expected.".FormatWith(CultureInfo.InvariantCulture, jToken.Type)); } return (JObject)jToken; } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { writer.WriteStartObject(); for (int i = 0; i < _properties.Count; i++) { _properties[i].WriteTo(writer, converters); } writer.WriteEndObject(); } public JToken? GetValue(string? propertyName) { return GetValue(propertyName, StringComparison.Ordinal); } public JToken? GetValue(string? propertyName, StringComparison comparison) { if (propertyName == null) { return null; } return Property(propertyName, comparison)?.Value; } public bool TryGetValue(string propertyName, StringComparison comparison, [NotNullWhen(true)] out JToken? value) { value = GetValue(propertyName, comparison); return value != null; } public void Add(string propertyName, JToken? value) { Add(new JProperty(propertyName, value)); } public bool ContainsKey(string propertyName) { ValidationUtils.ArgumentNotNull(propertyName, "propertyName"); return _properties.Contains(propertyName); } public bool Remove(string propertyName) { JProperty jProperty = Property(propertyName, StringComparison.Ordinal); if (jProperty == null) { return false; } jProperty.Remove(); return true; } public bool TryGetValue(string propertyName, [NotNullWhen(true)] out JToken? value) { JProperty jProperty = Property(propertyName, StringComparison.Ordinal); if (jProperty == null) { value = null; return false; } value = jProperty.Value; return true; } void ICollection>.Add(KeyValuePair item) { Add(new JProperty(item.Key, item.Value)); } void ICollection>.Clear() { RemoveAll(); } bool ICollection>.Contains(KeyValuePair item) { JProperty jProperty = Property(item.Key, StringComparison.Ordinal); if (jProperty == null) { return false; } return jProperty.Value == item.Value; } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } if (arrayIndex < 0) { throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0."); } if (arrayIndex >= array.Length && arrayIndex != 0) { throw new ArgumentException("arrayIndex is equal to or greater than the length of array."); } if (base.Count > array.Length - arrayIndex) { throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array."); } int num = 0; foreach (JProperty property in _properties) { array[arrayIndex + num] = new KeyValuePair(property.Name, property.Value); num++; } } bool ICollection>.Remove(KeyValuePair item) { if (!((ICollection>)this).Contains(item)) { return false; } ((IDictionary)this).Remove(item.Key); return true; } internal override int GetDeepHashCode() { return ContentsHashCode(); } public IEnumerator> GetEnumerator() { foreach (JProperty property in _properties) { yield return new KeyValuePair(property.Name, property.Value); } } protected virtual void OnPropertyChanged(string propertyName) { this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected virtual void OnPropertyChanging(string propertyName) { this.PropertyChanging?.Invoke(this, new PropertyChangingEventArgs(propertyName)); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { return ((ICustomTypeDescriptor)this).GetProperties((Attribute[]?)null); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[]? attributes) { PropertyDescriptor[] array = new PropertyDescriptor[base.Count]; int num = 0; using (IEnumerator> enumerator = GetEnumerator()) { while (enumerator.MoveNext()) { array[num] = new JPropertyDescriptor(enumerator.Current.Key); num++; } } return new PropertyDescriptorCollection(array); } AttributeCollection ICustomTypeDescriptor.GetAttributes() { return AttributeCollection.Empty; } string? ICustomTypeDescriptor.GetClassName() { return null; } string? ICustomTypeDescriptor.GetComponentName() { return null; } TypeConverter ICustomTypeDescriptor.GetConverter() { return new TypeConverter(); } EventDescriptor? ICustomTypeDescriptor.GetDefaultEvent() { return null; } PropertyDescriptor? ICustomTypeDescriptor.GetDefaultProperty() { return null; } object? ICustomTypeDescriptor.GetEditor(Type editorBaseType) { return null; } EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[]? attributes) { return EventDescriptorCollection.Empty; } EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { return EventDescriptorCollection.Empty; } object? ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor? pd) { if (pd is JPropertyDescriptor) { return this; } return null; } protected override DynamicMetaObject GetMetaObject(Expression parameter) { return new DynamicProxyMetaObject(parameter, this, new JObjectDynamicProxy()); } } internal class JProperty : JContainer { private class JPropertyList : IList, ICollection, IEnumerable, IEnumerable { internal JToken? _token; public int Count { get { if (_token == null) { return 0; } return 1; } } public bool IsReadOnly => false; public JToken this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _token; } set { if (index != 0) { throw new IndexOutOfRangeException(); } _token = value; } } public IEnumerator GetEnumerator() { if (_token != null) { yield return _token; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public void Add(JToken item) { _token = item; } public void Clear() { _token = null; } public bool Contains(JToken item) { return _token == item; } public void CopyTo(JToken[] array, int arrayIndex) { if (_token != null) { array[arrayIndex] = _token; } } public bool Remove(JToken item) { if (_token == item) { _token = null; return true; } return false; } public int IndexOf(JToken item) { if (_token != item) { return -1; } return 0; } public void Insert(int index, JToken item) { if (index == 0) { _token = item; } } public void RemoveAt(int index) { if (index == 0) { _token = null; } } } private readonly JPropertyList _content = new JPropertyList(); private readonly string _name; protected override IList ChildrenTokens => _content; public string Name { [DebuggerStepThrough] get { return _name; } } public new JToken Value { [DebuggerStepThrough] get { return _content._token; } set { CheckReentrancy(); JToken item = value ?? JValue.CreateNull(); if (_content._token == null) { InsertItem(0, item, skipParentCheck: false, copyAnnotations: true); } else { SetItem(0, item); } } } public override JTokenType Type { [DebuggerStepThrough] get { return JTokenType.Property; } } public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { Task task = writer.WritePropertyNameAsync(_name, cancellationToken); if (task.IsCompletedSuccessfully()) { return WriteValueAsync(writer, cancellationToken, converters); } return WriteToAsync(task, writer, cancellationToken, converters); } private async Task WriteToAsync(Task task, JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { await task.ConfigureAwait(continueOnCapturedContext: false); await WriteValueAsync(writer, cancellationToken, converters).ConfigureAwait(continueOnCapturedContext: false); } private Task WriteValueAsync(JsonWriter writer, CancellationToken cancellationToken, JsonConverter[] converters) { JToken value = Value; if (value == null) { return writer.WriteNullAsync(cancellationToken); } return value.WriteToAsync(writer, cancellationToken, converters); } public new static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public new static async Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { if (reader.TokenType == JsonToken.None && !(await reader.ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader."); } await reader.MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (reader.TokenType != JsonToken.PropertyName) { throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JProperty p = new JProperty((string)reader.Value); p.SetLineInfo(reader as IJsonLineInfo, settings); await p.ReadTokenFromAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return p; } public JProperty(JProperty other) : base(other, null) { _name = other.Name; } internal JProperty(JProperty other, JsonCloneSettings? settings) : base(other, settings) { _name = other.Name; } internal override JToken GetItem(int index) { if (index != 0) { throw new ArgumentOutOfRangeException(); } return Value; } internal override void SetItem(int index, JToken? item) { if (index != 0) { throw new ArgumentOutOfRangeException(); } if (!JContainer.IsTokenUnchanged(Value, item)) { ((JObject)base.Parent)?.InternalPropertyChanging(this); base.SetItem(0, item); ((JObject)base.Parent)?.InternalPropertyChanged(this); } } internal override bool RemoveItem(JToken? item) { throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } internal override void RemoveItemAt(int index) { throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } internal override int IndexOfItem(JToken? item) { if (item == null) { return -1; } return _content.IndexOf(item); } internal override bool InsertItem(int index, JToken? item, bool skipParentCheck, bool copyAnnotations) { if (item != null && item.Type == JTokenType.Comment) { return false; } if (Value != null) { throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } return base.InsertItem(0, item, skipParentCheck: false, copyAnnotations); } internal override bool ContainsItem(JToken? item) { return Value == item; } internal override void MergeItem(object content, JsonMergeSettings? settings) { JToken jToken = (content as JProperty)?.Value; if (jToken != null && jToken.Type != JTokenType.Null) { Value = jToken; } } internal override void ClearItems() { throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty))); } internal override bool DeepEquals(JToken node) { if (node is JProperty jProperty && _name == jProperty.Name) { return ContentsEqual(jProperty); } return false; } internal override JToken CloneToken(JsonCloneSettings? settings) { return new JProperty(this, settings); } internal JProperty(string name) { ValidationUtils.ArgumentNotNull(name, "name"); _name = name; } public JProperty(string name, params object[] content) : this(name, (object?)content) { } public JProperty(string name, object? content) { ValidationUtils.ArgumentNotNull(name, "name"); _name = name; Value = (IsMultiContent(content) ? new JArray(content) : JContainer.CreateFromContent(content)); } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { writer.WritePropertyName(_name); JToken value = Value; if (value != null) { value.WriteTo(writer, converters); } else { writer.WriteNull(); } } internal override int GetDeepHashCode() { return _name.GetHashCode() ^ (Value?.GetDeepHashCode() ?? 0); } public new static JProperty Load(JsonReader reader) { return Load(reader, null); } public new static JProperty Load(JsonReader reader, JsonLoadSettings? settings) { if (reader.TokenType == JsonToken.None && !reader.Read()) { throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader."); } reader.MoveToContent(); if (reader.TokenType != JsonToken.PropertyName) { throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } JProperty jProperty = new JProperty((string)reader.Value); jProperty.SetLineInfo(reader as IJsonLineInfo, settings); jProperty.ReadTokenFrom(reader, settings); return jProperty; } } internal class JPropertyDescriptor : PropertyDescriptor { public override Type ComponentType => typeof(JObject); public override bool IsReadOnly => false; public override Type PropertyType => typeof(object); protected override int NameHashCode => base.NameHashCode; public JPropertyDescriptor(string name) : base(name, null) { } private static JObject CastInstance(object instance) { return (JObject)instance; } public override bool CanResetValue(object component) { return false; } public override object? GetValue(object? component) { return (component as JObject)?[Name]; } public override void ResetValue(object component) { } public override void SetValue(object? component, object? value) { if (component is JObject jObject) { JToken value2 = (value as JToken) ?? new JValue(value); jObject[Name] = value2; } } public override bool ShouldSerializeValue(object component) { return false; } } internal class JPropertyKeyedCollection : Collection { private static readonly IEqualityComparer Comparer = StringComparer.Ordinal; private Dictionary? _dictionary; public JToken this[string key] { get { if (key == null) { throw new ArgumentNullException("key"); } if (_dictionary != null) { return _dictionary[key]; } throw new KeyNotFoundException(); } } public ICollection Keys { get { EnsureDictionary(); return _dictionary.Keys; } } public ICollection Values { get { EnsureDictionary(); return _dictionary.Values; } } public JPropertyKeyedCollection() : base((IList)new List()) { } private void AddKey(string key, JToken item) { EnsureDictionary(); _dictionary[key] = item; } protected void ChangeItemKey(JToken item, string newKey) { if (!ContainsItem(item)) { throw new ArgumentException("The specified item does not exist in this KeyedCollection."); } string keyForItem = GetKeyForItem(item); if (!Comparer.Equals(keyForItem, newKey)) { if (newKey != null) { AddKey(newKey, item); } if (keyForItem != null) { RemoveKey(keyForItem); } } } protected override void ClearItems() { base.ClearItems(); _dictionary?.Clear(); } public bool Contains(string key) { if (key == null) { throw new ArgumentNullException("key"); } if (_dictionary != null) { return _dictionary.ContainsKey(key); } return false; } private bool ContainsItem(JToken item) { if (_dictionary == null) { return false; } string keyForItem = GetKeyForItem(item); JToken value; return _dictionary.TryGetValue(keyForItem, out value); } private void EnsureDictionary() { if (_dictionary == null) { _dictionary = new Dictionary(Comparer); } } private string GetKeyForItem(JToken item) { return ((JProperty)item).Name; } protected override void InsertItem(int index, JToken item) { AddKey(GetKeyForItem(item), item); base.InsertItem(index, item); } public bool Remove(string key) { if (key == null) { throw new ArgumentNullException("key"); } if (_dictionary != null) { if (_dictionary.TryGetValue(key, out JToken value)) { return Remove(value); } return false; } return false; } protected override void RemoveItem(int index) { string keyForItem = GetKeyForItem(base.Items[index]); RemoveKey(keyForItem); base.RemoveItem(index); } private void RemoveKey(string key) { _dictionary?.Remove(key); } protected override void SetItem(int index, JToken item) { string keyForItem = GetKeyForItem(item); string keyForItem2 = GetKeyForItem(base.Items[index]); if (Comparer.Equals(keyForItem2, keyForItem)) { if (_dictionary != null) { _dictionary[keyForItem] = item; } } else { AddKey(keyForItem, item); if (keyForItem2 != null) { RemoveKey(keyForItem2); } } base.SetItem(index, item); } public bool TryGetValue(string key, [NotNullWhen(true)] out JToken? value) { if (_dictionary == null) { value = null; return false; } return _dictionary.TryGetValue(key, out value); } public int IndexOfReference(JToken t) { return ((List)base.Items).IndexOfReference(t); } public bool Compare(JPropertyKeyedCollection other) { if (this == other) { return true; } Dictionary dictionary = _dictionary; Dictionary dictionary2 = other._dictionary; if (dictionary == null && dictionary2 == null) { return true; } if (dictionary == null) { return dictionary2.Count == 0; } if (dictionary2 == null) { return dictionary.Count == 0; } if (dictionary.Count != dictionary2.Count) { return false; } foreach (KeyValuePair item in dictionary) { if (!dictionary2.TryGetValue(item.Key, out var value)) { return false; } JProperty jProperty = (JProperty)item.Value; JProperty jProperty2 = (JProperty)value; if (jProperty.Value == null) { return jProperty2.Value == null; } if (!jProperty.Value.DeepEquals(jProperty2.Value)) { return false; } } return true; } } internal class JRaw : JValue { public static async Task CreateAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { using StringWriter sw = new StringWriter(CultureInfo.InvariantCulture); using JsonTextWriter jsonWriter = new JsonTextWriter(sw); await jsonWriter.WriteTokenSyncReadingAsync(reader, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return new JRaw(sw.ToString()); } public JRaw(JRaw other) : base(other, null) { } internal JRaw(JRaw other, JsonCloneSettings? settings) : base(other, settings) { } public JRaw(object? rawJson) : base(rawJson, JTokenType.Raw) { } public static JRaw Create(JsonReader reader) { using StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); using JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter); jsonTextWriter.WriteToken(reader); return new JRaw(stringWriter.ToString()); } internal override JToken CloneToken(JsonCloneSettings? settings) { return new JRaw(this, settings); } } internal class JsonCloneSettings { internal static readonly JsonCloneSettings SkipCopyAnnotations = new JsonCloneSettings { CopyAnnotations = false }; public bool CopyAnnotations { get; set; } public JsonCloneSettings() { CopyAnnotations = true; } } internal class JsonLoadSettings { private CommentHandling _commentHandling; private LineInfoHandling _lineInfoHandling; private DuplicatePropertyNameHandling _duplicatePropertyNameHandling; public CommentHandling CommentHandling { get { return _commentHandling; } set { if (value < CommentHandling.Ignore || value > CommentHandling.Load) { throw new ArgumentOutOfRangeException("value"); } _commentHandling = value; } } public LineInfoHandling LineInfoHandling { get { return _lineInfoHandling; } set { if (value < LineInfoHandling.Ignore || value > LineInfoHandling.Load) { throw new ArgumentOutOfRangeException("value"); } _lineInfoHandling = value; } } public DuplicatePropertyNameHandling DuplicatePropertyNameHandling { get { return _duplicatePropertyNameHandling; } set { if (value < DuplicatePropertyNameHandling.Replace || value > DuplicatePropertyNameHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _duplicatePropertyNameHandling = value; } } public JsonLoadSettings() { _lineInfoHandling = LineInfoHandling.Load; _commentHandling = CommentHandling.Ignore; _duplicatePropertyNameHandling = DuplicatePropertyNameHandling.Replace; } } internal class JsonMergeSettings { private MergeArrayHandling _mergeArrayHandling; private MergeNullValueHandling _mergeNullValueHandling; private StringComparison _propertyNameComparison; public MergeArrayHandling MergeArrayHandling { get { return _mergeArrayHandling; } set { if (value < MergeArrayHandling.Concat || value > MergeArrayHandling.Merge) { throw new ArgumentOutOfRangeException("value"); } _mergeArrayHandling = value; } } public MergeNullValueHandling MergeNullValueHandling { get { return _mergeNullValueHandling; } set { if (value < MergeNullValueHandling.Ignore || value > MergeNullValueHandling.Merge) { throw new ArgumentOutOfRangeException("value"); } _mergeNullValueHandling = value; } } public StringComparison PropertyNameComparison { get { return _propertyNameComparison; } set { if (value < StringComparison.CurrentCulture || value > StringComparison.OrdinalIgnoreCase) { throw new ArgumentOutOfRangeException("value"); } _propertyNameComparison = value; } } public JsonMergeSettings() { _propertyNameComparison = StringComparison.Ordinal; } } internal class JsonSelectSettings { public TimeSpan? RegexMatchTimeout { get; set; } public bool ErrorWhenNoMatch { get; set; } } internal abstract class JToken : IJEnumerable, IEnumerable, IEnumerable, IJsonLineInfo, ICloneable, IDynamicMetaObjectProvider { private class LineInfoAnnotation { internal readonly int LineNumber; internal readonly int LinePosition; public LineInfoAnnotation(int lineNumber, int linePosition) { LineNumber = lineNumber; LinePosition = linePosition; } } private static JTokenEqualityComparer? _equalityComparer; private JContainer? _parent; private JToken? _previous; private JToken? _next; private object? _annotations; private static readonly JTokenType[] BooleanTypes = new JTokenType[6] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; private static readonly JTokenType[] NumberTypes = new JTokenType[6] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean }; private static readonly JTokenType[] BigIntegerTypes = new JTokenType[7] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes }; private static readonly JTokenType[] StringTypes = new JTokenType[11] { JTokenType.Date, JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes, JTokenType.Guid, JTokenType.TimeSpan, JTokenType.Uri }; private static readonly JTokenType[] GuidTypes = new JTokenType[5] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Guid, JTokenType.Bytes }; private static readonly JTokenType[] TimeSpanTypes = new JTokenType[4] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.TimeSpan }; private static readonly JTokenType[] UriTypes = new JTokenType[4] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Uri }; private static readonly JTokenType[] CharTypes = new JTokenType[5] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw }; private static readonly JTokenType[] DateTimeTypes = new JTokenType[4] { JTokenType.Date, JTokenType.String, JTokenType.Comment, JTokenType.Raw }; private static readonly JTokenType[] BytesTypes = new JTokenType[5] { JTokenType.Bytes, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Integer }; public static JTokenEqualityComparer EqualityComparer { get { if (_equalityComparer == null) { _equalityComparer = new JTokenEqualityComparer(); } return _equalityComparer; } } public JContainer? Parent { [DebuggerStepThrough] get { return _parent; } internal set { _parent = value; } } public JToken Root { get { JContainer parent = Parent; if (parent == null) { return this; } while (parent.Parent != null) { parent = parent.Parent; } return parent; } } public abstract JTokenType Type { get; } public abstract bool HasValues { get; } public JToken? Next { get { return _next; } internal set { _next = value; } } public JToken? Previous { get { return _previous; } internal set { _previous = value; } } public string Path { get { if (Parent == null) { return string.Empty; } List list = new List(); JToken jToken = null; for (JToken jToken2 = this; jToken2 != null; jToken2 = jToken2.Parent) { switch (jToken2.Type) { case JTokenType.Property: { JProperty jProperty = (JProperty)jToken2; list.Add(new JsonPosition(JsonContainerType.Object) { PropertyName = jProperty.Name }); break; } case JTokenType.Array: case JTokenType.Constructor: if (jToken != null) { int position = ((IList)jToken2).IndexOf(jToken); list.Add(new JsonPosition(JsonContainerType.Array) { Position = position }); } break; } jToken = jToken2; } list.FastReverse(); return JsonPosition.BuildPath(list, null); } } public virtual JToken? this[object key] { get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } set { throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } } public virtual JToken? First { get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } } public virtual JToken? Last { get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } } IJEnumerable IJEnumerable.this[object key] => this[key]; int IJsonLineInfo.LineNumber => Annotation()?.LineNumber ?? 0; int IJsonLineInfo.LinePosition => Annotation()?.LinePosition ?? 0; public virtual Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { throw new NotImplementedException(); } public Task WriteToAsync(JsonWriter writer, params JsonConverter[] converters) { return WriteToAsync(writer, default(CancellationToken), converters); } public static Task ReadFromAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return ReadFromAsync(reader, null, cancellationToken); } public static async Task ReadFromAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (reader.TokenType == JsonToken.None && !(await ((settings != null && settings.CommentHandling == CommentHandling.Ignore) ? reader.ReadAndMoveToContentAsync(cancellationToken) : reader.ReadAsync(cancellationToken)).ConfigureAwait(continueOnCapturedContext: false))) { throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader."); } IJsonLineInfo lineInfo = reader as IJsonLineInfo; switch (reader.TokenType) { case JsonToken.StartObject: return await JObject.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case JsonToken.StartArray: return await JArray.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case JsonToken.StartConstructor: return await JConstructor.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case JsonToken.PropertyName: return await JProperty.LoadAsync(reader, settings, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { JValue jValue4 = new JValue(reader.Value); jValue4.SetLineInfo(lineInfo, settings); return jValue4; } case JsonToken.Comment: { JValue jValue3 = JValue.CreateComment(reader.Value?.ToString()); jValue3.SetLineInfo(lineInfo, settings); return jValue3; } case JsonToken.Null: { JValue jValue2 = JValue.CreateNull(); jValue2.SetLineInfo(lineInfo, settings); return jValue2; } case JsonToken.Undefined: { JValue jValue = JValue.CreateUndefined(); jValue.SetLineInfo(lineInfo, settings); return jValue; } default: throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } public static Task LoadAsync(JsonReader reader, CancellationToken cancellationToken = default(CancellationToken)) { return LoadAsync(reader, null, cancellationToken); } public static Task LoadAsync(JsonReader reader, JsonLoadSettings? settings, CancellationToken cancellationToken = default(CancellationToken)) { return ReadFromAsync(reader, settings, cancellationToken); } internal abstract JToken CloneToken(JsonCloneSettings? settings); internal abstract bool DeepEquals(JToken node); public static bool DeepEquals(JToken? t1, JToken? t2) { if (t1 != t2) { if (t1 != null && t2 != null) { return t1.DeepEquals(t2); } return false; } return true; } internal JToken() { } public void AddAfterSelf(object? content) { if (_parent == null) { throw new InvalidOperationException("The parent is missing."); } int num = _parent.IndexOfItem(this); _parent.TryAddInternal(num + 1, content, skipParentCheck: false, copyAnnotations: true); } public void AddBeforeSelf(object? content) { if (_parent == null) { throw new InvalidOperationException("The parent is missing."); } int index = _parent.IndexOfItem(this); _parent.TryAddInternal(index, content, skipParentCheck: false, copyAnnotations: true); } public IEnumerable Ancestors() { return GetAncestors(self: false); } public IEnumerable AncestorsAndSelf() { return GetAncestors(self: true); } internal IEnumerable GetAncestors(bool self) { for (JToken current = (self ? this : Parent); current != null; current = current.Parent) { yield return current; } } public IEnumerable AfterSelf() { if (Parent != null) { for (JToken o = Next; o != null; o = o.Next) { yield return o; } } } public IEnumerable BeforeSelf() { if (Parent != null) { JToken o = Parent.First; while (o != this && o != null) { yield return o; o = o.Next; } } } public virtual T? Value(object key) { JToken jToken = this[key]; if (jToken != null) { return jToken.Convert(); } return default(T); } public virtual JEnumerable Children() { return JEnumerable.Empty; } public JEnumerable Children() where T : JToken { return new JEnumerable(Children().OfType()); } public virtual IEnumerable Values() { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); } public void Remove() { if (_parent == null) { throw new InvalidOperationException("The parent is missing."); } _parent.RemoveItem(this); } public void Replace(JToken value) { if (_parent == null) { throw new InvalidOperationException("The parent is missing."); } _parent.ReplaceItem(this, value); } public abstract void WriteTo(JsonWriter writer, params JsonConverter[] converters); public override string ToString() { return ToString(Formatting.Indented); } public string ToString(Formatting formatting, params JsonConverter[] converters) { using StringWriter stringWriter = new StringWriter(CultureInfo.InvariantCulture); JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter); jsonTextWriter.Formatting = formatting; WriteTo(jsonTextWriter, converters); return stringWriter.ToString(); } private static JValue? EnsureValue(JToken value) { if (value == null) { throw new ArgumentNullException("value"); } if (value is JProperty jProperty) { value = jProperty.Value; } return value as JValue; } private static string GetType(JToken token) { ValidationUtils.ArgumentNotNull(token, "token"); if (token is JProperty jProperty) { token = jProperty.Value; } return token.Type.ToString(); } private static bool ValidateToken(JToken o, JTokenType[] validTypes, bool nullable) { if (Array.IndexOf(validTypes, o.Type) == -1) { if (nullable) { if (o.Type != JTokenType.Null) { return o.Type == JTokenType.Undefined; } return true; } return false; } return true; } public static explicit operator bool(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BooleanTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return Convert.ToBoolean((int)bigInteger); } return Convert.ToBoolean(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator DateTimeOffset(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, DateTimeTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } object value2 = jValue.Value; if (value2 is DateTimeOffset) { return (DateTimeOffset)value2; } if (jValue.Value is string input) { return DateTimeOffset.Parse(input, CultureInfo.InvariantCulture); } return new DateTimeOffset(Convert.ToDateTime(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator bool?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BooleanTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return Convert.ToBoolean((int)bigInteger); } if (jValue.Value == null) { return null; } return Convert.ToBoolean(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator long(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (long)bigInteger; } return Convert.ToInt64(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator DateTime?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, DateTimeTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is DateTimeOffset dateTimeOffset) { return dateTimeOffset.DateTime; } if (jValue.Value == null) { return null; } return Convert.ToDateTime(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator DateTimeOffset?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, DateTimeTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } object value2 = jValue.Value; if (value2 is DateTimeOffset) { return (DateTimeOffset)value2; } if (jValue.Value is string input) { return DateTimeOffset.Parse(input, CultureInfo.InvariantCulture); } return new DateTimeOffset(Convert.ToDateTime(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator decimal?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (decimal)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToDecimal(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator double?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (double)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToDouble(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator char?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, CharTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (char)(ushort)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToChar(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator int(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (int)bigInteger; } return Convert.ToInt32(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator short(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (short)bigInteger; } return Convert.ToInt16(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator ushort(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (ushort)bigInteger; } return Convert.ToUInt16(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator char(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, CharTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (char)(ushort)bigInteger; } return Convert.ToChar(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator byte(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (byte)bigInteger; } return Convert.ToByte(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator sbyte(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (sbyte)bigInteger; } return Convert.ToSByte(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator int?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (int)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToInt32(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator short?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (short)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToInt16(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator ushort?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (ushort)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToUInt16(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator byte?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (byte)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToByte(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator sbyte?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (sbyte)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToSByte(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator DateTime(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, DateTimeTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is DateTimeOffset dateTimeOffset) { return dateTimeOffset.DateTime; } return Convert.ToDateTime(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator long?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (long)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToInt64(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator float?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (float)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToSingle(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator decimal(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (decimal)bigInteger; } return Convert.ToDecimal(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator uint?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (uint)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToUInt32(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator ulong?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (ulong)bigInteger; } if (jValue.Value == null) { return null; } return Convert.ToUInt64(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator double(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (double)bigInteger; } return Convert.ToDouble(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator float(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (float)bigInteger; } return Convert.ToSingle(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator string?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, StringTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to String.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } if (jValue.Value is byte[] inArray) { return Convert.ToBase64String(inArray); } if (jValue.Value is BigInteger bigInteger) { return bigInteger.ToString(CultureInfo.InvariantCulture); } return Convert.ToString(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator uint(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (uint)bigInteger; } return Convert.ToUInt32(jValue.Value, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static explicit operator ulong(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, NumberTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is BigInteger bigInteger) { return (ulong)bigInteger; } return Convert.ToUInt64(jValue.Value, CultureInfo.InvariantCulture); } public static explicit operator byte[]?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BytesTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is string) { return Convert.FromBase64String(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } if (jValue.Value is BigInteger bigInteger) { return bigInteger.ToByteArray(); } if (jValue.Value is byte[] result) { return result; } throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } public static explicit operator Guid(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, GuidTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value is byte[] b) { return new Guid(b); } object value2 = jValue.Value; if (value2 is Guid) { return (Guid)value2; } return new Guid(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator Guid?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, GuidTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } if (jValue.Value is byte[] b) { return new Guid(b); } return (jValue.Value is Guid guid) ? guid : new Guid(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator TimeSpan(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, TimeSpanTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } object value2 = jValue.Value; if (value2 is TimeSpan) { return (TimeSpan)value2; } return ConvertUtils.ParseTimeSpan(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator TimeSpan?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, TimeSpanTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } return (jValue.Value is TimeSpan timeSpan) ? timeSpan : ConvertUtils.ParseTimeSpan(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } public static explicit operator Uri?(JToken? value) { if (value == null) { return null; } JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, UriTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to Uri.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } if (!(jValue.Value is Uri result)) { return new Uri(Convert.ToString(jValue.Value, CultureInfo.InvariantCulture)); } return result; } private static BigInteger ToBigInteger(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BigIntegerTypes, nullable: false)) { throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } return ConvertUtils.ToBigInteger(jValue.Value); } private static BigInteger? ToBigIntegerNullable(JToken value) { JValue jValue = EnsureValue(value); if (jValue == null || !ValidateToken(jValue, BigIntegerTypes, nullable: true)) { throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value))); } if (jValue.Value == null) { return null; } return ConvertUtils.ToBigInteger(jValue.Value); } public static implicit operator JToken(bool value) { return new JValue(value); } public static implicit operator JToken(DateTimeOffset value) { return new JValue(value); } public static implicit operator JToken(byte value) { return new JValue(value); } public static implicit operator JToken(byte? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(sbyte value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(sbyte? value) { return new JValue(value); } public static implicit operator JToken(bool? value) { return new JValue(value); } public static implicit operator JToken(long value) { return new JValue(value); } public static implicit operator JToken(DateTime? value) { return new JValue(value); } public static implicit operator JToken(DateTimeOffset? value) { return new JValue(value); } public static implicit operator JToken(decimal? value) { return new JValue(value); } public static implicit operator JToken(double? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(short value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(ushort value) { return new JValue(value); } public static implicit operator JToken(int value) { return new JValue(value); } public static implicit operator JToken(int? value) { return new JValue(value); } public static implicit operator JToken(DateTime value) { return new JValue(value); } public static implicit operator JToken(long? value) { return new JValue(value); } public static implicit operator JToken(float? value) { return new JValue(value); } public static implicit operator JToken(decimal value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(short? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(ushort? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(uint? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(ulong? value) { return new JValue(value); } public static implicit operator JToken(double value) { return new JValue(value); } public static implicit operator JToken(float value) { return new JValue(value); } public static implicit operator JToken(string? value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(uint value) { return new JValue(value); } [CLSCompliant(false)] public static implicit operator JToken(ulong value) { return new JValue(value); } public static implicit operator JToken(byte[] value) { return new JValue(value); } public static implicit operator JToken(Uri? value) { return new JValue(value); } public static implicit operator JToken(TimeSpan value) { return new JValue(value); } public static implicit operator JToken(TimeSpan? value) { return new JValue(value); } public static implicit operator JToken(Guid value) { return new JValue(value); } public static implicit operator JToken(Guid? value) { return new JValue(value); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return Children().GetEnumerator(); } internal abstract int GetDeepHashCode(); public JsonReader CreateReader() { return new JTokenReader(this); } internal static JToken FromObjectInternal(object o, JsonSerializer jsonSerializer) { ValidationUtils.ArgumentNotNull(o, "o"); ValidationUtils.ArgumentNotNull(jsonSerializer, "jsonSerializer"); using JTokenWriter jTokenWriter = new JTokenWriter(); jsonSerializer.Serialize(jTokenWriter, o); return jTokenWriter.Token; } public static JToken FromObject(object o) { return FromObjectInternal(o, JsonSerializer.CreateDefault()); } public static JToken FromObject(object o, JsonSerializer jsonSerializer) { return FromObjectInternal(o, jsonSerializer); } public T? ToObject() { return (T)ToObject(typeof(T)); } public object? ToObject(Type objectType) { if (JsonConvert.DefaultSettings == null) { bool isEnum; PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(objectType, out isEnum); if (isEnum) { if (Type == JTokenType.String) { try { return ToObject(objectType, JsonSerializer.CreateDefault()); } catch (Exception innerException) { Type type = (objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType)); throw new ArgumentException("Could not convert '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, (string?)this, type.Name), innerException); } } if (Type == JTokenType.Integer) { return Enum.ToObject(objectType.IsEnum() ? objectType : Nullable.GetUnderlyingType(objectType), ((JValue)this).Value); } } switch (typeCode) { case PrimitiveTypeCode.BooleanNullable: return (bool?)this; case PrimitiveTypeCode.Boolean: return (bool)this; case PrimitiveTypeCode.CharNullable: return (char?)this; case PrimitiveTypeCode.Char: return (char)this; case PrimitiveTypeCode.SByte: return (sbyte)this; case PrimitiveTypeCode.SByteNullable: return (sbyte?)this; case PrimitiveTypeCode.ByteNullable: return (byte?)this; case PrimitiveTypeCode.Byte: return (byte)this; case PrimitiveTypeCode.Int16Nullable: return (short?)this; case PrimitiveTypeCode.Int16: return (short)this; case PrimitiveTypeCode.UInt16Nullable: return (ushort?)this; case PrimitiveTypeCode.UInt16: return (ushort)this; case PrimitiveTypeCode.Int32Nullable: return (int?)this; case PrimitiveTypeCode.Int32: return (int)this; case PrimitiveTypeCode.UInt32Nullable: return (uint?)this; case PrimitiveTypeCode.UInt32: return (uint)this; case PrimitiveTypeCode.Int64Nullable: return (long?)this; case PrimitiveTypeCode.Int64: return (long)this; case PrimitiveTypeCode.UInt64Nullable: return (ulong?)this; case PrimitiveTypeCode.UInt64: return (ulong)this; case PrimitiveTypeCode.SingleNullable: return (float?)this; case PrimitiveTypeCode.Single: return (float)this; case PrimitiveTypeCode.DoubleNullable: return (double?)this; case PrimitiveTypeCode.Double: return (double)this; case PrimitiveTypeCode.DecimalNullable: return (decimal?)this; case PrimitiveTypeCode.Decimal: return (decimal)this; case PrimitiveTypeCode.DateTimeNullable: return (DateTime?)this; case PrimitiveTypeCode.DateTime: return (DateTime)this; case PrimitiveTypeCode.DateTimeOffsetNullable: return (DateTimeOffset?)this; case PrimitiveTypeCode.DateTimeOffset: return (DateTimeOffset)this; case PrimitiveTypeCode.String: return (string?)this; case PrimitiveTypeCode.GuidNullable: return (Guid?)this; case PrimitiveTypeCode.Guid: return (Guid)this; case PrimitiveTypeCode.Uri: return (Uri?)this; case PrimitiveTypeCode.TimeSpanNullable: return (TimeSpan?)this; case PrimitiveTypeCode.TimeSpan: return (TimeSpan)this; case PrimitiveTypeCode.BigIntegerNullable: return ToBigIntegerNullable(this); case PrimitiveTypeCode.BigInteger: return ToBigInteger(this); } } return ToObject(objectType, JsonSerializer.CreateDefault()); } public T? ToObject(JsonSerializer jsonSerializer) { return (T)ToObject(typeof(T), jsonSerializer); } public object? ToObject(Type? objectType, JsonSerializer jsonSerializer) { ValidationUtils.ArgumentNotNull(jsonSerializer, "jsonSerializer"); using JTokenReader reader = new JTokenReader(this); if (jsonSerializer is JsonSerializerProxy jsonSerializerProxy) { jsonSerializerProxy._serializer.SetupReader(reader, out CultureInfo _, out DateTimeZoneHandling? _, out DateParseHandling? _, out FloatParseHandling? _, out int? _, out string _); } return jsonSerializer.Deserialize(reader, objectType); } public static JToken ReadFrom(JsonReader reader) { return ReadFrom(reader, null); } public static JToken ReadFrom(JsonReader reader, JsonLoadSettings? settings) { ValidationUtils.ArgumentNotNull(reader, "reader"); if (!((reader.TokenType == JsonToken.None) ? ((settings != null && settings.CommentHandling == CommentHandling.Ignore) ? reader.ReadAndMoveToContent() : reader.Read()) : (reader.TokenType != JsonToken.Comment || settings == null || settings.CommentHandling != 0 || reader.ReadAndMoveToContent()))) { throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader."); } IJsonLineInfo lineInfo = reader as IJsonLineInfo; switch (reader.TokenType) { case JsonToken.StartObject: return JObject.Load(reader, settings); case JsonToken.StartArray: return JArray.Load(reader, settings); case JsonToken.StartConstructor: return JConstructor.Load(reader, settings); case JsonToken.PropertyName: return JProperty.Load(reader, settings); case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { JValue jValue4 = new JValue(reader.Value); jValue4.SetLineInfo(lineInfo, settings); return jValue4; } case JsonToken.Comment: { JValue jValue3 = JValue.CreateComment(reader.Value.ToString()); jValue3.SetLineInfo(lineInfo, settings); return jValue3; } case JsonToken.Null: { JValue jValue2 = JValue.CreateNull(); jValue2.SetLineInfo(lineInfo, settings); return jValue2; } case JsonToken.Undefined: { JValue jValue = JValue.CreateUndefined(); jValue.SetLineInfo(lineInfo, settings); return jValue; } default: throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } public static JToken Parse(string json) { return Parse(json, null); } public static JToken Parse(string json, JsonLoadSettings? settings) { using JsonReader jsonReader = new JsonTextReader(new StringReader(json)); JToken result = Load(jsonReader, settings); while (jsonReader.Read()) { } return result; } public static JToken Load(JsonReader reader, JsonLoadSettings? settings) { return ReadFrom(reader, settings); } public static JToken Load(JsonReader reader) { return Load(reader, null); } internal void SetLineInfo(IJsonLineInfo? lineInfo, JsonLoadSettings? settings) { if ((settings == null || settings.LineInfoHandling == LineInfoHandling.Load) && lineInfo != null && lineInfo.HasLineInfo()) { SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition); } } internal void SetLineInfo(int lineNumber, int linePosition) { AddAnnotation(new LineInfoAnnotation(lineNumber, linePosition)); } bool IJsonLineInfo.HasLineInfo() { return Annotation() != null; } public JToken? SelectToken(string path) { return SelectToken(path, null); } public JToken? SelectToken(string path, bool errorWhenNoMatch) { JsonSelectSettings settings = (errorWhenNoMatch ? new JsonSelectSettings { ErrorWhenNoMatch = true } : null); return SelectToken(path, settings); } public JToken? SelectToken(string path, JsonSelectSettings? settings) { JPath jPath = new JPath(path); JToken jToken = null; foreach (JToken item in jPath.Evaluate(this, this, settings)) { if (jToken != null) { throw new JsonException("Path returned multiple tokens."); } jToken = item; } return jToken; } public IEnumerable SelectTokens(string path) { return SelectTokens(path, null); } public IEnumerable SelectTokens(string path, bool errorWhenNoMatch) { JsonSelectSettings settings = (errorWhenNoMatch ? new JsonSelectSettings { ErrorWhenNoMatch = true } : null); return SelectTokens(path, settings); } public IEnumerable SelectTokens(string path, JsonSelectSettings? settings) { return new JPath(path).Evaluate(this, this, settings); } protected virtual DynamicMetaObject GetMetaObject(Expression parameter) { return new DynamicProxyMetaObject(parameter, this, new DynamicProxy()); } DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter) { return GetMetaObject(parameter); } object ICloneable.Clone() { return DeepClone(); } public JToken DeepClone() { return CloneToken(null); } public JToken DeepClone(JsonCloneSettings settings) { return CloneToken(settings); } public void AddAnnotation(object annotation) { if (annotation == null) { throw new ArgumentNullException("annotation"); } if (_annotations == null) { _annotations = ((!(annotation is object[])) ? annotation : new object[1] { annotation }); return; } object[] array = _annotations as object[]; if (array == null) { _annotations = new object[2] { _annotations, annotation }; return; } int i; for (i = 0; i < array.Length && array[i] != null; i++) { } if (i == array.Length) { Array.Resize(ref array, i * 2); _annotations = array; } array[i] = annotation; } public T? Annotation() where T : class { if (_annotations != null) { if (!(_annotations is object[] array)) { return _annotations as T; } foreach (object obj in array) { if (obj == null) { break; } if (obj is T result) { return result; } } } return null; } public object? Annotation(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (_annotations != null) { if (!(_annotations is object[] array)) { if (type.IsInstanceOfType(_annotations)) { return _annotations; } } else { foreach (object obj in array) { if (obj == null) { break; } if (type.IsInstanceOfType(obj)) { return obj; } } } } return null; } public IEnumerable Annotations() where T : class { if (_annotations == null) { yield break; } object annotations2 = _annotations; object[] annotations = annotations2 as object[]; if (annotations != null) { foreach (object obj in annotations) { if (obj != null) { if (obj is T val) { yield return val; } continue; } break; } } else if (_annotations is T val2) { yield return val2; } } public IEnumerable Annotations(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (_annotations == null) { yield break; } object annotations2 = _annotations; object[] annotations = annotations2 as object[]; if (annotations != null) { foreach (object obj in annotations) { if (obj != null) { if (type.IsInstanceOfType(obj)) { yield return obj; } continue; } break; } } else if (type.IsInstanceOfType(_annotations)) { yield return _annotations; } } public void RemoveAnnotations() where T : class { if (_annotations == null) { return; } if (!(_annotations is object[] array)) { if (_annotations is T) { _annotations = null; } return; } int i = 0; int num = 0; for (; i < array.Length; i++) { object obj = array[i]; if (obj == null) { break; } if (!(obj is T)) { array[num++] = obj; } } if (num != 0) { while (num < i) { array[num++] = null; } } else { _annotations = null; } } public void RemoveAnnotations(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (_annotations == null) { return; } if (!(_annotations is object[] array)) { if (type.IsInstanceOfType(_annotations)) { _annotations = null; } return; } int i = 0; int num = 0; for (; i < array.Length; i++) { object obj = array[i]; if (obj == null) { break; } if (!type.IsInstanceOfType(obj)) { array[num++] = obj; } } if (num != 0) { while (num < i) { array[num++] = null; } } else { _annotations = null; } } internal void CopyAnnotations(JToken target, JToken source) { if (source._annotations is object[] source2) { target._annotations = source2.ToArray(); } else { target._annotations = source._annotations; } } } internal class JTokenEqualityComparer : IEqualityComparer { public bool Equals(JToken? x, JToken? y) { return JToken.DeepEquals(x, y); } public int GetHashCode(JToken obj) { return obj?.GetDeepHashCode() ?? 0; } } internal class JTokenReader : JsonReader, IJsonLineInfo { private readonly JToken _root; private string? _initialPath; private JToken? _parent; private JToken? _current; public JToken? CurrentToken => _current; int IJsonLineInfo.LineNumber { get { if (base.CurrentState == State.Start) { return 0; } return ((IJsonLineInfo)_current)?.LineNumber ?? 0; } } int IJsonLineInfo.LinePosition { get { if (base.CurrentState == State.Start) { return 0; } return ((IJsonLineInfo)_current)?.LinePosition ?? 0; } } public override string Path { get { string text = base.Path; if (_initialPath == null) { _initialPath = _root.Path; } if (!StringUtils.IsNullOrEmpty(_initialPath)) { if (StringUtils.IsNullOrEmpty(text)) { return _initialPath; } text = ((!StringUtils.StartsWith(text, '[')) ? (_initialPath + "." + text) : (_initialPath + text)); } return text; } } public JTokenReader(JToken token) { ValidationUtils.ArgumentNotNull(token, "token"); _root = token; } public JTokenReader(JToken token, string initialPath) : this(token) { _initialPath = initialPath; } public override bool Read() { if (base.CurrentState != 0) { if (_current == null) { return false; } if (_current is JContainer jContainer && _parent != jContainer) { return ReadInto(jContainer); } return ReadOver(_current); } if (_current == _root) { return false; } _current = _root; SetToken(_current); return true; } private bool ReadOver(JToken t) { if (t == _root) { return ReadToEnd(); } JToken next = t.Next; if (next == null || next == t || t == t.Parent.Last) { if (t.Parent == null) { return ReadToEnd(); } return SetEnd(t.Parent); } _current = next; SetToken(_current); return true; } private bool ReadToEnd() { _current = null; SetToken(JsonToken.None); return false; } private JsonToken? GetEndToken(JContainer c) { return c.Type switch { JTokenType.Object => JsonToken.EndObject, JTokenType.Array => JsonToken.EndArray, JTokenType.Constructor => JsonToken.EndConstructor, JTokenType.Property => null, _ => throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", c.Type, "Unexpected JContainer type."), }; } private bool ReadInto(JContainer c) { JToken first = c.First; if (first == null) { return SetEnd(c); } SetToken(first); _current = first; _parent = c; return true; } private bool SetEnd(JContainer c) { JsonToken? endToken = GetEndToken(c); if (endToken.HasValue) { SetToken(endToken.GetValueOrDefault()); _current = c; _parent = c; return true; } return ReadOver(c); } private void SetToken(JToken token) { switch (token.Type) { case JTokenType.Object: SetToken(JsonToken.StartObject); break; case JTokenType.Array: SetToken(JsonToken.StartArray); break; case JTokenType.Constructor: SetToken(JsonToken.StartConstructor, ((JConstructor)token).Name); break; case JTokenType.Property: SetToken(JsonToken.PropertyName, ((JProperty)token).Name); break; case JTokenType.Comment: SetToken(JsonToken.Comment, ((JValue)token).Value); break; case JTokenType.Integer: SetToken(JsonToken.Integer, ((JValue)token).Value); break; case JTokenType.Float: SetToken(JsonToken.Float, ((JValue)token).Value); break; case JTokenType.String: SetToken(JsonToken.String, ((JValue)token).Value); break; case JTokenType.Boolean: SetToken(JsonToken.Boolean, ((JValue)token).Value); break; case JTokenType.Null: SetToken(JsonToken.Null, ((JValue)token).Value); break; case JTokenType.Undefined: SetToken(JsonToken.Undefined, ((JValue)token).Value); break; case JTokenType.Date: { object obj = ((JValue)token).Value; if (obj is DateTime value2) { obj = DateTimeUtils.EnsureDateTime(value2, base.DateTimeZoneHandling); } SetToken(JsonToken.Date, obj); break; } case JTokenType.Raw: SetToken(JsonToken.Raw, ((JValue)token).Value); break; case JTokenType.Bytes: SetToken(JsonToken.Bytes, ((JValue)token).Value); break; case JTokenType.Guid: SetToken(JsonToken.String, SafeToString(((JValue)token).Value)); break; case JTokenType.Uri: { object value = ((JValue)token).Value; SetToken(JsonToken.String, (value is Uri uri) ? uri.OriginalString : SafeToString(value)); break; } case JTokenType.TimeSpan: SetToken(JsonToken.String, SafeToString(((JValue)token).Value)); break; default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", token.Type, "Unexpected JTokenType."); } } private string? SafeToString(object? value) { return value?.ToString(); } bool IJsonLineInfo.HasLineInfo() { if (base.CurrentState == State.Start) { return false; } return ((IJsonLineInfo)_current)?.HasLineInfo() ?? false; } } internal enum JTokenType { None, Object, Array, Constructor, Property, Comment, Integer, Float, String, Boolean, Null, Undefined, Date, Raw, Bytes, Guid, Uri, TimeSpan } internal class JTokenWriter : JsonWriter { private JContainer? _token; private JContainer? _parent; private JValue? _value; private JToken? _current; public JToken? CurrentToken => _current; public JToken? Token { get { if (_token != null) { return _token; } return _value; } } internal override Task WriteTokenAsync(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments, CancellationToken cancellationToken) { if (reader is JTokenReader) { WriteToken(reader, writeChildren, writeDateConstructorAsDate, writeComments); return AsyncUtils.CompletedTask; } return WriteTokenSyncReadingAsync(reader, cancellationToken); } public JTokenWriter(JContainer container) { ValidationUtils.ArgumentNotNull(container, "container"); _token = container; _parent = container; } public JTokenWriter() { } public override void Flush() { } public override void Close() { base.Close(); } public override void WriteStartObject() { base.WriteStartObject(); AddParent(new JObject()); } private void AddParent(JContainer container) { if (_parent == null) { _token = container; } else { _parent.AddAndSkipParentCheck(container); } _parent = container; _current = container; } private void RemoveParent() { _current = _parent; _parent = _parent.Parent; if (_parent != null && _parent.Type == JTokenType.Property) { _parent = _parent.Parent; } } public override void WriteStartArray() { base.WriteStartArray(); AddParent(new JArray()); } public override void WriteStartConstructor(string name) { base.WriteStartConstructor(name); AddParent(new JConstructor(name)); } protected override void WriteEnd(JsonToken token) { RemoveParent(); } public override void WritePropertyName(string name) { (_parent as JObject)?.Remove(name); AddParent(new JProperty(name)); base.WritePropertyName(name); } private void AddRawValue(object? value, JTokenType type, JsonToken token) { AddJValue(new JValue(value, type), token); } internal void AddJValue(JValue? value, JsonToken token) { if (_parent != null) { if (_parent.TryAdd(value)) { _current = _parent.Last; if (_parent.Type == JTokenType.Property) { _parent = _parent.Parent; } } } else { _value = value ?? JValue.CreateNull(); _current = _value; } } public override void WriteValue(object? value) { if (value is BigInteger) { InternalWriteValue(JsonToken.Integer); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } else { base.WriteValue(value); } } public override void WriteNull() { base.WriteNull(); AddJValue(JValue.CreateNull(), JsonToken.Null); } public override void WriteUndefined() { base.WriteUndefined(); AddJValue(JValue.CreateUndefined(), JsonToken.Undefined); } public override void WriteRaw(string? json) { base.WriteRaw(json); AddJValue(new JRaw(json), JsonToken.Raw); } public override void WriteComment(string? text) { base.WriteComment(text); AddJValue(JValue.CreateComment(text), JsonToken.Comment); } public override void WriteValue(string? value) { if (value == null) { WriteNull(); return; } base.WriteValue(value); AddJValue(new JValue(value), JsonToken.String); } public override void WriteValue(int value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } [CLSCompliant(false)] public override void WriteValue(uint value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } public override void WriteValue(long value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Integer); } [CLSCompliant(false)] public override void WriteValue(ulong value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Integer); } public override void WriteValue(float value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Float); } public override void WriteValue(double value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Float); } public override void WriteValue(bool value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Boolean); } public override void WriteValue(short value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } [CLSCompliant(false)] public override void WriteValue(ushort value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } public override void WriteValue(char value) { base.WriteValue(value); string value2 = value.ToString(CultureInfo.InvariantCulture); AddJValue(new JValue(value2), JsonToken.String); } public override void WriteValue(byte value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } [CLSCompliant(false)] public override void WriteValue(sbyte value) { base.WriteValue(value); AddRawValue(value, JTokenType.Integer, JsonToken.Integer); } public override void WriteValue(decimal value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Float); } public override void WriteValue(DateTime value) { base.WriteValue(value); value = DateTimeUtils.EnsureDateTime(value, base.DateTimeZoneHandling); AddJValue(new JValue(value), JsonToken.Date); } public override void WriteValue(DateTimeOffset value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.Date); } public override void WriteValue(byte[]? value) { base.WriteValue(value); AddJValue(new JValue(value, JTokenType.Bytes), JsonToken.Bytes); } public override void WriteValue(TimeSpan value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.String); } public override void WriteValue(Guid value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.String); } public override void WriteValue(Uri? value) { base.WriteValue(value); AddJValue(new JValue(value), JsonToken.String); } internal override void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate, bool writeComments) { JTokenReader jTokenReader = reader as JTokenReader; if (jTokenReader != null && writeChildren && writeDateConstructorAsDate && writeComments) { if (jTokenReader.TokenType == JsonToken.None && !jTokenReader.Read()) { return; } JToken jToken = jTokenReader.CurrentToken.CloneToken(null); if (_parent != null) { _parent.Add(jToken); _current = _parent.Last; if (_parent.Type == JTokenType.Property) { _parent = _parent.Parent; InternalWriteValue(JsonToken.Null); } } else { _current = jToken; if (_token == null && _value == null) { _token = jToken as JContainer; _value = jToken as JValue; } } jTokenReader.Skip(); } else { base.WriteToken(reader, writeChildren, writeDateConstructorAsDate, writeComments); } } } internal class JValue : JToken, IEquatable, IFormattable, IComparable, IComparable, IConvertible { private class JValueDynamicProxy : DynamicProxy { public override bool TryConvert(JValue instance, ConvertBinder binder, [NotNullWhen(true)] out object? result) { if (binder.Type == typeof(JValue) || binder.Type == typeof(JToken)) { result = instance; return true; } object value = instance.Value; if (value == null) { result = null; return ReflectionUtils.IsNullable(binder.Type); } result = ConvertUtils.Convert(value, CultureInfo.InvariantCulture, binder.Type); return true; } public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, [NotNullWhen(true)] out object? result) { object objB = ((arg is JValue jValue) ? jValue.Value : arg); switch (binder.Operation) { case ExpressionType.Equal: result = Compare(instance.Type, instance.Value, objB) == 0; return true; case ExpressionType.NotEqual: result = Compare(instance.Type, instance.Value, objB) != 0; return true; case ExpressionType.GreaterThan: result = Compare(instance.Type, instance.Value, objB) > 0; return true; case ExpressionType.GreaterThanOrEqual: result = Compare(instance.Type, instance.Value, objB) >= 0; return true; case ExpressionType.LessThan: result = Compare(instance.Type, instance.Value, objB) < 0; return true; case ExpressionType.LessThanOrEqual: result = Compare(instance.Type, instance.Value, objB) <= 0; return true; case ExpressionType.Add: case ExpressionType.Divide: case ExpressionType.Multiply: case ExpressionType.Subtract: case ExpressionType.AddAssign: case ExpressionType.DivideAssign: case ExpressionType.MultiplyAssign: case ExpressionType.SubtractAssign: if (Operation(binder.Operation, instance.Value, objB, out result)) { result = new JValue(result); return true; } break; } result = null; return false; } } private JTokenType _valueType; private object? _value; public override bool HasValues => false; public override JTokenType Type => _valueType; public new object? Value { get { return _value; } set { Type obj = _value?.GetType(); Type type = value?.GetType(); if (obj != type) { _valueType = GetValueType(_valueType, value); } _value = value; } } public override Task WriteToAsync(JsonWriter writer, CancellationToken cancellationToken, params JsonConverter[] converters) { if (converters != null && converters.Length != 0 && _value != null) { JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); if (matchingConverter != null && matchingConverter.CanWrite) { matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault()); return AsyncUtils.CompletedTask; } } switch (_valueType) { case JTokenType.Comment: return writer.WriteCommentAsync(_value?.ToString(), cancellationToken); case JTokenType.Raw: return writer.WriteRawValueAsync(_value?.ToString(), cancellationToken); case JTokenType.Null: return writer.WriteNullAsync(cancellationToken); case JTokenType.Undefined: return writer.WriteUndefinedAsync(cancellationToken); case JTokenType.Integer: if (_value is int value5) { return writer.WriteValueAsync(value5, cancellationToken); } if (_value is long value6) { return writer.WriteValueAsync(value6, cancellationToken); } if (_value is ulong value7) { return writer.WriteValueAsync(value7, cancellationToken); } if (_value is BigInteger bigInteger) { return writer.WriteValueAsync(bigInteger, cancellationToken); } return writer.WriteValueAsync(Convert.ToInt64(_value, CultureInfo.InvariantCulture), cancellationToken); case JTokenType.Float: if (_value is decimal value) { return writer.WriteValueAsync(value, cancellationToken); } if (_value is double value2) { return writer.WriteValueAsync(value2, cancellationToken); } if (_value is float value3) { return writer.WriteValueAsync(value3, cancellationToken); } return writer.WriteValueAsync(Convert.ToDouble(_value, CultureInfo.InvariantCulture), cancellationToken); case JTokenType.String: return writer.WriteValueAsync(_value?.ToString(), cancellationToken); case JTokenType.Boolean: return writer.WriteValueAsync(Convert.ToBoolean(_value, CultureInfo.InvariantCulture), cancellationToken); case JTokenType.Date: if (_value is DateTimeOffset value4) { return writer.WriteValueAsync(value4, cancellationToken); } return writer.WriteValueAsync(Convert.ToDateTime(_value, CultureInfo.InvariantCulture), cancellationToken); case JTokenType.Bytes: return writer.WriteValueAsync((byte[])_value, cancellationToken); case JTokenType.Guid: return writer.WriteValueAsync((_value != null) ? ((Guid?)_value) : null, cancellationToken); case JTokenType.TimeSpan: return writer.WriteValueAsync((_value != null) ? ((TimeSpan?)_value) : null, cancellationToken); case JTokenType.Uri: return writer.WriteValueAsync((Uri)_value, cancellationToken); default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", _valueType, "Unexpected token type."); } } internal JValue(object? value, JTokenType type) { _value = value; _valueType = type; } internal JValue(JValue other, JsonCloneSettings? settings) : this(other.Value, other.Type) { if (settings == null || settings.CopyAnnotations) { CopyAnnotations(this, other); } } public JValue(JValue other) : this(other.Value, other.Type) { } public JValue(long value) : this(BoxedPrimitives.Get(value), JTokenType.Integer) { } public JValue(decimal value) : this(BoxedPrimitives.Get(value), JTokenType.Float) { } public JValue(char value) : this(value, JTokenType.String) { } [CLSCompliant(false)] public JValue(ulong value) : this(value, JTokenType.Integer) { } public JValue(double value) : this(BoxedPrimitives.Get(value), JTokenType.Float) { } public JValue(float value) : this(value, JTokenType.Float) { } public JValue(DateTime value) : this(value, JTokenType.Date) { } public JValue(DateTimeOffset value) : this(value, JTokenType.Date) { } public JValue(bool value) : this(BoxedPrimitives.Get(value), JTokenType.Boolean) { } public JValue(string? value) : this(value, JTokenType.String) { } public JValue(Guid value) : this(value, JTokenType.Guid) { } public JValue(Uri? value) : this(value, (value != null) ? JTokenType.Uri : JTokenType.Null) { } public JValue(TimeSpan value) : this(value, JTokenType.TimeSpan) { } public JValue(object? value) : this(value, GetValueType(null, value)) { } internal override bool DeepEquals(JToken node) { if (!(node is JValue jValue)) { return false; } if (jValue == this) { return true; } return ValuesEquals(this, jValue); } private static int CompareBigInteger(BigInteger i1, object i2) { int num = i1.CompareTo(ConvertUtils.ToBigInteger(i2)); if (num != 0) { return num; } if (i2 is decimal num2) { decimal num3 = 0m; return num3.CompareTo(Math.Abs(num2 - Math.Truncate(num2))); } if (i2 is double || i2 is float) { double num4 = Convert.ToDouble(i2, CultureInfo.InvariantCulture); return 0.0.CompareTo(Math.Abs(num4 - Math.Truncate(num4))); } return num; } internal static int Compare(JTokenType valueType, object? objA, object? objB) { if (objA == objB) { return 0; } if (objB == null) { return 1; } if (objA == null) { return -1; } switch (valueType) { case JTokenType.Integer: if (objA is BigInteger i3) { return CompareBigInteger(i3, objB); } if (objB is BigInteger i4) { return -CompareBigInteger(i4, objA); } if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) { return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture)); } if (objA is float || objB is float || objA is double || objB is double) { return CompareFloat(objA, objB); } return Convert.ToInt64(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToInt64(objB, CultureInfo.InvariantCulture)); case JTokenType.Float: if (objA is BigInteger i) { return CompareBigInteger(i, objB); } if (objB is BigInteger i2) { return -CompareBigInteger(i2, objA); } if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) { return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture)); } return CompareFloat(objA, objB); case JTokenType.Comment: case JTokenType.String: case JTokenType.Raw: { string? strA = Convert.ToString(objA, CultureInfo.InvariantCulture); string strB = Convert.ToString(objB, CultureInfo.InvariantCulture); return string.CompareOrdinal(strA, strB); } case JTokenType.Boolean: { bool flag = Convert.ToBoolean(objA, CultureInfo.InvariantCulture); bool value4 = Convert.ToBoolean(objB, CultureInfo.InvariantCulture); return flag.CompareTo(value4); } case JTokenType.Date: { if (objA is DateTime dateTime) { DateTime value2 = ((!(objB is DateTimeOffset dateTimeOffset)) ? Convert.ToDateTime(objB, CultureInfo.InvariantCulture) : dateTimeOffset.DateTime); return dateTime.CompareTo(value2); } DateTimeOffset dateTimeOffset2 = (DateTimeOffset)objA; DateTimeOffset other = ((!(objB is DateTimeOffset)) ? new DateTimeOffset(Convert.ToDateTime(objB, CultureInfo.InvariantCulture)) : ((DateTimeOffset)objB)); return dateTimeOffset2.CompareTo(other); } case JTokenType.Bytes: if (!(objB is byte[] a)) { throw new ArgumentException("Object must be of type byte[]."); } return MiscellaneousUtils.ByteArrayCompare(objA as byte[], a); case JTokenType.Guid: { if (!(objB is Guid)) { throw new ArgumentException("Object must be of type Guid."); } Guid guid = (Guid)objA; Guid value3 = (Guid)objB; return guid.CompareTo(value3); } case JTokenType.Uri: { Uri uri = objB as Uri; if (uri == null) { throw new ArgumentException("Object must be of type Uri."); } Uri uri2 = (Uri)objA; return Comparer.Default.Compare(uri2.ToString(), uri.ToString()); } case JTokenType.TimeSpan: { if (!(objB is TimeSpan)) { throw new ArgumentException("Object must be of type TimeSpan."); } TimeSpan timeSpan = (TimeSpan)objA; TimeSpan value = (TimeSpan)objB; return timeSpan.CompareTo(value); } default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("valueType", valueType, "Unexpected value type: {0}".FormatWith(CultureInfo.InvariantCulture, valueType)); } } private static int CompareFloat(object objA, object objB) { double d = Convert.ToDouble(objA, CultureInfo.InvariantCulture); double num = Convert.ToDouble(objB, CultureInfo.InvariantCulture); if (MathUtils.ApproxEquals(d, num)) { return 0; } return d.CompareTo(num); } private static bool Operation(ExpressionType operation, object? objA, object? objB, out object? result) { if ((objA is string || objB is string) && (operation == ExpressionType.Add || operation == ExpressionType.AddAssign)) { result = objA?.ToString() + objB; return true; } if (objA is BigInteger || objB is BigInteger) { if (objA == null || objB == null) { result = null; return true; } BigInteger bigInteger = ConvertUtils.ToBigInteger(objA); BigInteger bigInteger2 = ConvertUtils.ToBigInteger(objB); switch (operation) { case ExpressionType.Add: case ExpressionType.AddAssign: result = bigInteger + bigInteger2; return true; case ExpressionType.Subtract: case ExpressionType.SubtractAssign: result = bigInteger - bigInteger2; return true; case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: result = bigInteger * bigInteger2; return true; case ExpressionType.Divide: case ExpressionType.DivideAssign: result = bigInteger / bigInteger2; return true; } } else if (objA is ulong || objB is ulong || objA is decimal || objB is decimal) { if (objA == null || objB == null) { result = null; return true; } decimal num = Convert.ToDecimal(objA, CultureInfo.InvariantCulture); decimal num2 = Convert.ToDecimal(objB, CultureInfo.InvariantCulture); switch (operation) { case ExpressionType.Add: case ExpressionType.AddAssign: result = num + num2; return true; case ExpressionType.Subtract: case ExpressionType.SubtractAssign: result = num - num2; return true; case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: result = num * num2; return true; case ExpressionType.Divide: case ExpressionType.DivideAssign: result = num / num2; return true; } } else if (objA is float || objB is float || objA is double || objB is double) { if (objA == null || objB == null) { result = null; return true; } double num3 = Convert.ToDouble(objA, CultureInfo.InvariantCulture); double num4 = Convert.ToDouble(objB, CultureInfo.InvariantCulture); switch (operation) { case ExpressionType.Add: case ExpressionType.AddAssign: result = num3 + num4; return true; case ExpressionType.Subtract: case ExpressionType.SubtractAssign: result = num3 - num4; return true; case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: result = num3 * num4; return true; case ExpressionType.Divide: case ExpressionType.DivideAssign: result = num3 / num4; return true; } } else if (objA is int || objA is uint || objA is long || objA is short || objA is ushort || objA is sbyte || objA is byte || objB is int || objB is uint || objB is long || objB is short || objB is ushort || objB is sbyte || objB is byte) { if (objA == null || objB == null) { result = null; return true; } long num5 = Convert.ToInt64(objA, CultureInfo.InvariantCulture); long num6 = Convert.ToInt64(objB, CultureInfo.InvariantCulture); switch (operation) { case ExpressionType.Add: case ExpressionType.AddAssign: result = num5 + num6; return true; case ExpressionType.Subtract: case ExpressionType.SubtractAssign: result = num5 - num6; return true; case ExpressionType.Multiply: case ExpressionType.MultiplyAssign: result = num5 * num6; return true; case ExpressionType.Divide: case ExpressionType.DivideAssign: result = num5 / num6; return true; } } result = null; return false; } internal override JToken CloneToken(JsonCloneSettings? settings) { return new JValue(this, settings); } public static JValue CreateComment(string? value) { return new JValue(value, JTokenType.Comment); } public static JValue CreateString(string? value) { return new JValue(value, JTokenType.String); } public static JValue CreateNull() { return new JValue(null, JTokenType.Null); } public static JValue CreateUndefined() { return new JValue(null, JTokenType.Undefined); } private static JTokenType GetValueType(JTokenType? current, object? value) { if (value == null) { return JTokenType.Null; } if (value == DBNull.Value) { return JTokenType.Null; } if (value is string) { return GetStringValueType(current); } if (value is long || value is int || value is short || value is sbyte || value is ulong || value is uint || value is ushort || value is byte) { return JTokenType.Integer; } if (value is Enum) { return JTokenType.Integer; } if (value is BigInteger) { return JTokenType.Integer; } if (value is double || value is float || value is decimal) { return JTokenType.Float; } if (value is DateTime) { return JTokenType.Date; } if (value is DateTimeOffset) { return JTokenType.Date; } if (value is byte[]) { return JTokenType.Bytes; } if (value is bool) { return JTokenType.Boolean; } if (value is Guid) { return JTokenType.Guid; } if (value is Uri) { return JTokenType.Uri; } if (value is TimeSpan) { return JTokenType.TimeSpan; } throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } private static JTokenType GetStringValueType(JTokenType? current) { if (!current.HasValue) { return JTokenType.String; } JTokenType valueOrDefault = current.GetValueOrDefault(); if (valueOrDefault == JTokenType.Comment || valueOrDefault == JTokenType.String || valueOrDefault == JTokenType.Raw) { return current.GetValueOrDefault(); } return JTokenType.String; } public override void WriteTo(JsonWriter writer, params JsonConverter[] converters) { if (converters != null && converters.Length != 0 && _value != null) { JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType()); if (matchingConverter != null && matchingConverter.CanWrite) { matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault()); return; } } switch (_valueType) { case JTokenType.Comment: writer.WriteComment(_value?.ToString()); break; case JTokenType.Raw: writer.WriteRawValue(_value?.ToString()); break; case JTokenType.Null: writer.WriteNull(); break; case JTokenType.Undefined: writer.WriteUndefined(); break; case JTokenType.Integer: if (_value is int value5) { writer.WriteValue(value5); } else if (_value is long value6) { writer.WriteValue(value6); } else if (_value is ulong value7) { writer.WriteValue(value7); } else if (_value is BigInteger bigInteger) { writer.WriteValue(bigInteger); } else { writer.WriteValue(Convert.ToInt64(_value, CultureInfo.InvariantCulture)); } break; case JTokenType.Float: if (_value is decimal value) { writer.WriteValue(value); } else if (_value is double value2) { writer.WriteValue(value2); } else if (_value is float value3) { writer.WriteValue(value3); } else { writer.WriteValue(Convert.ToDouble(_value, CultureInfo.InvariantCulture)); } break; case JTokenType.String: writer.WriteValue(_value?.ToString()); break; case JTokenType.Boolean: writer.WriteValue(Convert.ToBoolean(_value, CultureInfo.InvariantCulture)); break; case JTokenType.Date: if (_value is DateTimeOffset value4) { writer.WriteValue(value4); } else { writer.WriteValue(Convert.ToDateTime(_value, CultureInfo.InvariantCulture)); } break; case JTokenType.Bytes: writer.WriteValue((byte[])_value); break; case JTokenType.Guid: writer.WriteValue((_value != null) ? ((Guid?)_value) : null); break; case JTokenType.TimeSpan: writer.WriteValue((_value != null) ? ((TimeSpan?)_value) : null); break; case JTokenType.Uri: writer.WriteValue((Uri)_value); break; default: throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", _valueType, "Unexpected token type."); } } internal override int GetDeepHashCode() { int num = ((_value != null) ? _value.GetHashCode() : 0); int valueType = (int)_valueType; return valueType.GetHashCode() ^ num; } private static bool ValuesEquals(JValue v1, JValue v2) { if (v1 != v2) { if (v1._valueType == v2._valueType) { return Compare(v1._valueType, v1._value, v2._value) == 0; } return false; } return true; } public bool Equals(JValue? other) { if (other == null) { return false; } return ValuesEquals(this, other); } public override bool Equals(object? obj) { if (obj is JValue other) { return Equals(other); } return false; } public override int GetHashCode() { if (_value == null) { return 0; } return _value.GetHashCode(); } public override string ToString() { if (_value == null) { return string.Empty; } return _value.ToString(); } public string ToString(string format) { return ToString(format, CultureInfo.CurrentCulture); } public string ToString(IFormatProvider? formatProvider) { return ToString(null, formatProvider); } public string ToString(string? format, IFormatProvider? formatProvider) { if (_value == null) { return string.Empty; } if (_value is IFormattable formattable) { return formattable.ToString(format, formatProvider); } return _value.ToString(); } protected override DynamicMetaObject GetMetaObject(Expression parameter) { return new DynamicProxyMetaObject(parameter, this, new JValueDynamicProxy()); } int IComparable.CompareTo(object? obj) { if (obj == null) { return 1; } object objB; JTokenType valueType; if (obj is JValue jValue) { objB = jValue.Value; valueType = ((_valueType == JTokenType.String && _valueType != jValue._valueType) ? jValue._valueType : _valueType); } else { objB = obj; valueType = _valueType; } return Compare(valueType, _value, objB); } public int CompareTo(JValue? obj) { if (obj == null) { return 1; } return Compare((_valueType == JTokenType.String && _valueType != obj._valueType) ? obj._valueType : _valueType, _value, obj._value); } TypeCode IConvertible.GetTypeCode() { if (_value == null) { return TypeCode.Empty; } if (_value is IConvertible convertible) { return convertible.GetTypeCode(); } return TypeCode.Object; } bool IConvertible.ToBoolean(IFormatProvider? provider) { return (bool)(JToken)this; } char IConvertible.ToChar(IFormatProvider? provider) { return (char)(JToken)this; } sbyte IConvertible.ToSByte(IFormatProvider? provider) { return (sbyte)(JToken)this; } byte IConvertible.ToByte(IFormatProvider? provider) { return (byte)(JToken)this; } short IConvertible.ToInt16(IFormatProvider? provider) { return (short)(JToken)this; } ushort IConvertible.ToUInt16(IFormatProvider? provider) { return (ushort)(JToken)this; } int IConvertible.ToInt32(IFormatProvider? provider) { return (int)(JToken)this; } uint IConvertible.ToUInt32(IFormatProvider? provider) { return (uint)(JToken)this; } long IConvertible.ToInt64(IFormatProvider? provider) { return (long)(JToken)this; } ulong IConvertible.ToUInt64(IFormatProvider? provider) { return (ulong)(JToken)this; } float IConvertible.ToSingle(IFormatProvider? provider) { return (float)(JToken)this; } double IConvertible.ToDouble(IFormatProvider? provider) { return (double)(JToken)this; } decimal IConvertible.ToDecimal(IFormatProvider? provider) { return (decimal)(JToken)this; } DateTime IConvertible.ToDateTime(IFormatProvider? provider) { return (DateTime)(JToken)this; } object IConvertible.ToType(Type conversionType, IFormatProvider? provider) { return ToObject(conversionType); } } internal enum LineInfoHandling { Ignore, Load } internal enum MergeArrayHandling { Concat, Union, Replace, Merge } [Flags] internal enum MergeNullValueHandling { Ignore = 0, Merge = 1 } } namespace Newtonsoft.Json.Linq.JsonPath { internal class ArrayIndexFilter : PathFilter { public int? Index { get; set; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { if (Index.HasValue) { JToken tokenIndex = PathFilter.GetTokenIndex(item, settings, Index.GetValueOrDefault()); if (tokenIndex != null) { yield return tokenIndex; } } else if (item is JArray || item is JConstructor) { foreach (JToken item2 in (IEnumerable)item) { yield return item2; } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Index * not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, item.GetType().Name)); } } } } internal class ArrayMultipleIndexFilter : PathFilter { internal List Indexes; public ArrayMultipleIndexFilter(List indexes) { Indexes = indexes; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken t in current) { foreach (int index in Indexes) { JToken tokenIndex = PathFilter.GetTokenIndex(t, settings, index); if (tokenIndex != null) { yield return tokenIndex; } } } } } internal class ArraySliceFilter : PathFilter { public int? Start { get; set; } public int? End { get; set; } public int? Step { get; set; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { if (Step == 0) { throw new JsonException("Step cannot be zero."); } foreach (JToken item in current) { if (item is JArray a) { int stepCount = Step ?? 1; int num = Start ?? ((stepCount <= 0) ? (a.Count - 1) : 0); int stopIndex = End ?? ((stepCount > 0) ? a.Count : (-1)); if (Start < 0) { num = a.Count + num; } if (End < 0) { stopIndex = a.Count + stopIndex; } num = Math.Max(num, (stepCount <= 0) ? int.MinValue : 0); num = Math.Min(num, (stepCount > 0) ? a.Count : (a.Count - 1)); stopIndex = Math.Max(stopIndex, -1); stopIndex = Math.Min(stopIndex, a.Count); bool positiveStep = stepCount > 0; if (IsValid(num, stopIndex, positiveStep)) { for (int i = num; IsValid(i, stopIndex, positiveStep); i += stepCount) { yield return a[i]; } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Array slice of {0} to {1} returned no results.".FormatWith(CultureInfo.InvariantCulture, Start.HasValue ? Start.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*", End.HasValue ? End.GetValueOrDefault().ToString(CultureInfo.InvariantCulture) : "*")); } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Array slice is not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, item.GetType().Name)); } } } private bool IsValid(int index, int stopIndex, bool positiveStep) { if (positiveStep) { return index < stopIndex; } return index > stopIndex; } } internal class FieldFilter : PathFilter { internal string? Name; public FieldFilter(string? name) { Name = name; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { if (item is JObject jObject) { if (Name != null) { JToken jToken = jObject[Name]; if (jToken != null) { yield return jToken; } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, Name)); } continue; } foreach (KeyValuePair item2 in jObject) { yield return item2.Value; } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, Name ?? "*", item.GetType().Name)); } } } } internal class FieldMultipleFilter : PathFilter { internal List Names; public FieldMultipleFilter(List names) { Names = names; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { if (item is JObject o) { foreach (string name in Names) { JToken jToken = o[name]; if (jToken != null) { yield return jToken; } if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, name)); } } } else if (settings?.ErrorWhenNoMatch ?? false) { throw new JsonException("Properties {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", Names.Select((string n) => "'" + n + "'")), item.GetType().Name)); } } } } internal class JPath { private static readonly char[] FloatCharacters = new char[3] { '.', 'E', 'e' }; private readonly string _expression; private int _currentIndex; public List Filters { get; } public JPath(string expression) { ValidationUtils.ArgumentNotNull(expression, "expression"); _expression = expression; Filters = new List(); ParseMain(); } private void ParseMain() { int currentIndex = _currentIndex; EatWhitespace(); if (_expression.Length == _currentIndex) { return; } if (_expression[_currentIndex] == '$') { if (_expression.Length == 1) { return; } char c = _expression[_currentIndex + 1]; if (c == '.' || c == '[') { _currentIndex++; currentIndex = _currentIndex; } } if (!ParsePath(Filters, currentIndex, query: false)) { int currentIndex2 = _currentIndex; EatWhitespace(); if (_currentIndex < _expression.Length) { throw new JsonException("Unexpected character while parsing path: " + _expression[currentIndex2]); } } } private bool ParsePath(List filters, int currentPartStartIndex, bool query) { bool scan = false; bool flag = false; bool flag2 = false; bool flag3 = false; while (_currentIndex < _expression.Length && !flag3) { char c = _expression[_currentIndex]; switch (c) { case '(': case '[': if (_currentIndex > currentPartStartIndex) { string text = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); if (text == "*") { text = null; } filters.Add(CreatePathFilter(text, scan)); scan = false; } filters.Add(ParseIndexer(c, scan)); scan = false; _currentIndex++; currentPartStartIndex = _currentIndex; flag = true; flag2 = false; break; case ')': case ']': flag3 = true; break; case ' ': if (_currentIndex < _expression.Length) { flag3 = true; } break; case '.': if (_currentIndex > currentPartStartIndex) { string text2 = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex); if (text2 == "*") { text2 = null; } filters.Add(CreatePathFilter(text2, scan)); scan = false; } if (_currentIndex + 1 < _expression.Length && _expression[_currentIndex + 1] == '.') { scan = true; _currentIndex++; } _currentIndex++; currentPartStartIndex = _currentIndex; flag = false; flag2 = true; break; default: if (query && (c == '=' || c == '<' || c == '!' || c == '>' || c == '|' || c == '&')) { flag3 = true; break; } if (flag) { throw new JsonException("Unexpected character following indexer: " + c); } _currentIndex++; break; } } bool flag4 = _currentIndex == _expression.Length; if (_currentIndex > currentPartStartIndex) { string text3 = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex).TrimEnd(new char[0]); if (text3 == "*") { text3 = null; } filters.Add(CreatePathFilter(text3, scan)); } else if (flag2 && (flag4 || query)) { throw new JsonException("Unexpected end while parsing path."); } return flag4; } private static PathFilter CreatePathFilter(string? member, bool scan) { if (!scan) { return new FieldFilter(member); } return new ScanFilter(member); } private PathFilter ParseIndexer(char indexerOpenChar, bool scan) { _currentIndex++; char indexerCloseChar = ((indexerOpenChar == '[') ? ']' : ')'); EnsureLength("Path ended with open indexer."); EatWhitespace(); if (_expression[_currentIndex] == '\'') { return ParseQuotedField(indexerCloseChar, scan); } if (_expression[_currentIndex] == '?') { return ParseQuery(indexerCloseChar, scan); } return ParseArrayIndexer(indexerCloseChar); } private PathFilter ParseArrayIndexer(char indexerCloseChar) { int currentIndex = _currentIndex; int? num = null; List list = null; int num2 = 0; int? start = null; int? end = null; int? step = null; while (_currentIndex < _expression.Length) { char c = _expression[_currentIndex]; if (c == ' ') { num = _currentIndex; EatWhitespace(); continue; } if (c == indexerCloseChar) { int num3 = (num ?? _currentIndex) - currentIndex; if (list != null) { if (num3 == 0) { throw new JsonException("Array index expected."); } int item = Convert.ToInt32(_expression.Substring(currentIndex, num3), CultureInfo.InvariantCulture); list.Add(item); return new ArrayMultipleIndexFilter(list); } if (num2 > 0) { if (num3 > 0) { int value = Convert.ToInt32(_expression.Substring(currentIndex, num3), CultureInfo.InvariantCulture); if (num2 == 1) { end = value; } else { step = value; } } return new ArraySliceFilter { Start = start, End = end, Step = step }; } if (num3 == 0) { throw new JsonException("Array index expected."); } int value2 = Convert.ToInt32(_expression.Substring(currentIndex, num3), CultureInfo.InvariantCulture); return new ArrayIndexFilter { Index = value2 }; } switch (c) { case ',': { int num5 = (num ?? _currentIndex) - currentIndex; if (num5 == 0) { throw new JsonException("Array index expected."); } if (list == null) { list = new List(); } string value4 = _expression.Substring(currentIndex, num5); list.Add(Convert.ToInt32(value4, CultureInfo.InvariantCulture)); _currentIndex++; EatWhitespace(); currentIndex = _currentIndex; num = null; break; } case '*': _currentIndex++; EnsureLength("Path ended with open indexer."); EatWhitespace(); if (_expression[_currentIndex] != indexerCloseChar) { throw new JsonException("Unexpected character while parsing path indexer: " + c); } return new ArrayIndexFilter(); case ':': { int num4 = (num ?? _currentIndex) - currentIndex; if (num4 > 0) { int value3 = Convert.ToInt32(_expression.Substring(currentIndex, num4), CultureInfo.InvariantCulture); switch (num2) { case 0: start = value3; break; case 1: end = value3; break; default: step = value3; break; } } num2++; _currentIndex++; EatWhitespace(); currentIndex = _currentIndex; num = null; break; } default: if (!char.IsDigit(c) && c != '-') { throw new JsonException("Unexpected character while parsing path indexer: " + c); } if (num.HasValue) { throw new JsonException("Unexpected character while parsing path indexer: " + c); } _currentIndex++; break; } } throw new JsonException("Path ended with open indexer."); } private void EatWhitespace() { while (_currentIndex < _expression.Length && _expression[_currentIndex] == ' ') { _currentIndex++; } } private PathFilter ParseQuery(char indexerCloseChar, bool scan) { _currentIndex++; EnsureLength("Path ended with open indexer."); if (_expression[_currentIndex] != '(') { throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]); } _currentIndex++; QueryExpression expression = ParseExpression(); _currentIndex++; EnsureLength("Path ended with open indexer."); EatWhitespace(); if (_expression[_currentIndex] != indexerCloseChar) { throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]); } if (!scan) { return new QueryFilter(expression); } return new QueryScanFilter(expression); } private bool TryParseExpression(out List? expressionPath) { if (_expression[_currentIndex] == '$') { expressionPath = new List { RootFilter.Instance }; } else { if (_expression[_currentIndex] != '@') { expressionPath = null; return false; } expressionPath = new List(); } _currentIndex++; if (ParsePath(expressionPath, _currentIndex, query: true)) { throw new JsonException("Path ended with open query."); } return true; } private JsonException CreateUnexpectedCharacterException() { return new JsonException("Unexpected character while parsing path query: " + _expression[_currentIndex]); } private object ParseSide() { EatWhitespace(); if (TryParseExpression(out List expressionPath)) { EatWhitespace(); EnsureLength("Path ended with open query."); return expressionPath; } if (TryParseValue(out object value)) { EatWhitespace(); EnsureLength("Path ended with open query."); return new JValue(value); } throw CreateUnexpectedCharacterException(); } private QueryExpression ParseExpression() { QueryExpression queryExpression = null; CompositeExpression compositeExpression = null; while (_currentIndex < _expression.Length) { object left = ParseSide(); object right = null; QueryOperator @operator; if (_expression[_currentIndex] == ')' || _expression[_currentIndex] == '|' || _expression[_currentIndex] == '&') { @operator = QueryOperator.Exists; } else { @operator = ParseOperator(); right = ParseSide(); } BooleanQueryExpression booleanQueryExpression = new BooleanQueryExpression(@operator, left, right); if (_expression[_currentIndex] == ')') { if (compositeExpression != null) { compositeExpression.Expressions.Add(booleanQueryExpression); return queryExpression; } return booleanQueryExpression; } if (_expression[_currentIndex] == '&') { if (!Match("&&")) { throw CreateUnexpectedCharacterException(); } if (compositeExpression == null || compositeExpression.Operator != QueryOperator.And) { CompositeExpression compositeExpression2 = new CompositeExpression(QueryOperator.And); compositeExpression?.Expressions.Add(compositeExpression2); compositeExpression = compositeExpression2; if (queryExpression == null) { queryExpression = compositeExpression; } } compositeExpression.Expressions.Add(booleanQueryExpression); } if (_expression[_currentIndex] != '|') { continue; } if (!Match("||")) { throw CreateUnexpectedCharacterException(); } if (compositeExpression == null || compositeExpression.Operator != QueryOperator.Or) { CompositeExpression compositeExpression3 = new CompositeExpression(QueryOperator.Or); compositeExpression?.Expressions.Add(compositeExpression3); compositeExpression = compositeExpression3; if (queryExpression == null) { queryExpression = compositeExpression; } } compositeExpression.Expressions.Add(booleanQueryExpression); } throw new JsonException("Path ended with open query."); } private bool TryParseValue(out object? value) { char c = _expression[_currentIndex]; if (c == '\'') { value = ReadQuotedString(); return true; } if (char.IsDigit(c) || c == '-') { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(c); _currentIndex++; while (_currentIndex < _expression.Length) { c = _expression[_currentIndex]; if (c == ' ' || c == ')') { string text = stringBuilder.ToString(); if (text.IndexOfAny(FloatCharacters) != -1) { double result; bool result2 = double.TryParse(text, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out result); value = result; return result2; } long result3; bool result4 = long.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out result3); value = result3; return result4; } stringBuilder.Append(c); _currentIndex++; } } else { switch (c) { case 't': if (Match("true")) { value = true; return true; } break; case 'f': if (Match("false")) { value = false; return true; } break; case 'n': if (Match("null")) { value = null; return true; } break; case '/': value = ReadRegexString(); return true; } } value = null; return false; } private string ReadQuotedString() { StringBuilder stringBuilder = new StringBuilder(); _currentIndex++; while (_currentIndex < _expression.Length) { char c = _expression[_currentIndex]; if (c == '\\' && _currentIndex + 1 < _expression.Length) { _currentIndex++; c = _expression[_currentIndex]; char value; switch (c) { case 'b': value = '\b'; break; case 't': value = '\t'; break; case 'n': value = '\n'; break; case 'f': value = '\f'; break; case 'r': value = '\r'; break; case '"': case '\'': case '/': case '\\': value = c; break; default: throw new JsonException("Unknown escape character: \\" + c); } stringBuilder.Append(value); _currentIndex++; } else { if (c == '\'') { _currentIndex++; return stringBuilder.ToString(); } _currentIndex++; stringBuilder.Append(c); } } throw new JsonException("Path ended with an open string."); } private string ReadRegexString() { int currentIndex = _currentIndex; _currentIndex++; while (_currentIndex < _expression.Length) { char c = _expression[_currentIndex]; if (c == '\\' && _currentIndex + 1 < _expression.Length) { _currentIndex += 2; continue; } if (c == '/') { _currentIndex++; while (_currentIndex < _expression.Length) { c = _expression[_currentIndex]; if (!char.IsLetter(c)) { break; } _currentIndex++; } return _expression.Substring(currentIndex, _currentIndex - currentIndex); } _currentIndex++; } throw new JsonException("Path ended with an open regex."); } private bool Match(string s) { int num = _currentIndex; for (int i = 0; i < s.Length; i++) { if (num < _expression.Length && _expression[num] == s[i]) { num++; continue; } return false; } _currentIndex = num; return true; } private QueryOperator ParseOperator() { if (_currentIndex + 1 >= _expression.Length) { throw new JsonException("Path ended with open query."); } if (Match("===")) { return QueryOperator.StrictEquals; } if (Match("==")) { return QueryOperator.Equals; } if (Match("=~")) { return QueryOperator.RegexEquals; } if (Match("!==")) { return QueryOperator.StrictNotEquals; } if (Match("!=") || Match("<>")) { return QueryOperator.NotEquals; } if (Match("<=")) { return QueryOperator.LessThanOrEquals; } if (Match("<")) { return QueryOperator.LessThan; } if (Match(">=")) { return QueryOperator.GreaterThanOrEquals; } if (Match(">")) { return QueryOperator.GreaterThan; } throw new JsonException("Could not read query operator."); } private PathFilter ParseQuotedField(char indexerCloseChar, bool scan) { List list = null; while (_currentIndex < _expression.Length) { string text = ReadQuotedString(); EatWhitespace(); EnsureLength("Path ended with open indexer."); if (_expression[_currentIndex] == indexerCloseChar) { if (list != null) { list.Add(text); if (!scan) { return new FieldMultipleFilter(list); } return new ScanMultipleFilter(list); } return CreatePathFilter(text, scan); } if (_expression[_currentIndex] == ',') { _currentIndex++; EatWhitespace(); if (list == null) { list = new List(); } list.Add(text); continue; } throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]); } throw new JsonException("Path ended with open indexer."); } private void EnsureLength(string message) { if (_currentIndex >= _expression.Length) { throw new JsonException(message); } } internal IEnumerable Evaluate(JToken root, JToken t, JsonSelectSettings? settings) { return Evaluate(Filters, root, t, settings); } internal static IEnumerable Evaluate(List filters, JToken root, JToken t, JsonSelectSettings? settings) { IEnumerable enumerable = new JToken[1] { t }; foreach (PathFilter filter in filters) { enumerable = filter.ExecuteFilter(root, enumerable, settings); } return enumerable; } } internal abstract class PathFilter { public abstract IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings); protected static JToken? GetTokenIndex(JToken t, JsonSelectSettings? settings, int index) { if (t is JArray jArray) { if (jArray.Count <= index) { if (settings != null && settings.ErrorWhenNoMatch) { throw new JsonException("Index {0} outside the bounds of JArray.".FormatWith(CultureInfo.InvariantCulture, index)); } return null; } return jArray[index]; } if (t is JConstructor jConstructor) { if (jConstructor.Count <= index) { if (settings != null && settings.ErrorWhenNoMatch) { throw new JsonException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index)); } return null; } return jConstructor[index]; } if (settings != null && settings.ErrorWhenNoMatch) { throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name)); } return null; } protected static JToken? GetNextScanValue(JToken originalParent, JToken? container, JToken? value) { if (container != null && container.HasValues) { value = container.First; } else { while (value != null && value != originalParent && value == value.Parent.Last) { value = value.Parent; } if (value == null || value == originalParent) { return null; } value = value.Next; } return value; } } internal enum QueryOperator { None, Equals, NotEquals, Exists, LessThan, LessThanOrEquals, GreaterThan, GreaterThanOrEquals, And, Or, RegexEquals, StrictEquals, StrictNotEquals } internal abstract class QueryExpression { internal QueryOperator Operator; public QueryExpression(QueryOperator @operator) { Operator = @operator; } public bool IsMatch(JToken root, JToken t) { return IsMatch(root, t, null); } public abstract bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings); } internal class CompositeExpression : QueryExpression { public List Expressions { get; set; } public CompositeExpression(QueryOperator @operator) : base(@operator) { Expressions = new List(); } public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) { switch (Operator) { case QueryOperator.And: foreach (QueryExpression expression in Expressions) { if (!expression.IsMatch(root, t, settings)) { return false; } } return true; case QueryOperator.Or: foreach (QueryExpression expression2 in Expressions) { if (expression2.IsMatch(root, t, settings)) { return true; } } return false; default: throw new ArgumentOutOfRangeException(); } } } internal class BooleanQueryExpression : QueryExpression { public readonly object Left; public readonly object? Right; public BooleanQueryExpression(QueryOperator @operator, object left, object? right) : base(@operator) { Left = left; Right = right; } private IEnumerable GetResult(JToken root, JToken t, object? o) { if (o is JToken jToken) { return new JToken[1] { jToken }; } if (o is List filters) { return JPath.Evaluate(filters, root, t, null); } return CollectionUtils.ArrayEmpty(); } public override bool IsMatch(JToken root, JToken t, JsonSelectSettings? settings) { if (Operator == QueryOperator.Exists) { return GetResult(root, t, Left).Any(); } using (IEnumerator enumerator = GetResult(root, t, Left).GetEnumerator()) { if (enumerator.MoveNext()) { IEnumerable result = GetResult(root, t, Right); ICollection collection = (result as ICollection) ?? result.ToList(); do { JToken current = enumerator.Current; foreach (JToken item in collection) { if (MatchTokens(current, item, settings)) { return true; } } } while (enumerator.MoveNext()); } } return false; } private bool MatchTokens(JToken leftResult, JToken rightResult, JsonSelectSettings? settings) { if (leftResult is JValue jValue && rightResult is JValue jValue2) { switch (Operator) { case QueryOperator.RegexEquals: if (RegexEquals(jValue, jValue2, settings)) { return true; } break; case QueryOperator.Equals: if (EqualsWithStringCoercion(jValue, jValue2)) { return true; } break; case QueryOperator.StrictEquals: if (EqualsWithStrictMatch(jValue, jValue2)) { return true; } break; case QueryOperator.NotEquals: if (!EqualsWithStringCoercion(jValue, jValue2)) { return true; } break; case QueryOperator.StrictNotEquals: if (!EqualsWithStrictMatch(jValue, jValue2)) { return true; } break; case QueryOperator.GreaterThan: if (jValue.CompareTo(jValue2) > 0) { return true; } break; case QueryOperator.GreaterThanOrEquals: if (jValue.CompareTo(jValue2) >= 0) { return true; } break; case QueryOperator.LessThan: if (jValue.CompareTo(jValue2) < 0) { return true; } break; case QueryOperator.LessThanOrEquals: if (jValue.CompareTo(jValue2) <= 0) { return true; } break; case QueryOperator.Exists: return true; } } else { QueryOperator @operator = Operator; if ((uint)(@operator - 2) <= 1u) { return true; } } return false; } private static bool RegexEquals(JValue input, JValue pattern, JsonSelectSettings? settings) { if (input.Type != JTokenType.String || pattern.Type != JTokenType.String) { return false; } string obj = (string)pattern.Value; int num = obj.LastIndexOf('/'); string pattern2 = obj.Substring(1, num - 1); string optionsText = obj.Substring(num + 1); TimeSpan matchTimeout = settings?.RegexMatchTimeout ?? Regex.InfiniteMatchTimeout; return Regex.IsMatch((string)input.Value, pattern2, MiscellaneousUtils.GetRegexOptions(optionsText), matchTimeout); } internal static bool EqualsWithStringCoercion(JValue value, JValue queryValue) { if (value.Equals(queryValue)) { return true; } if ((value.Type == JTokenType.Integer && queryValue.Type == JTokenType.Float) || (value.Type == JTokenType.Float && queryValue.Type == JTokenType.Integer)) { return JValue.Compare(value.Type, value.Value, queryValue.Value) == 0; } if (queryValue.Type != JTokenType.String) { return false; } string b = (string)queryValue.Value; string a; switch (value.Type) { case JTokenType.Date: { using (StringWriter stringWriter = StringUtils.CreateStringWriter(64)) { if (value.Value is DateTimeOffset value2) { DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value2, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture); } else { DateTimeUtils.WriteDateTimeString(stringWriter, (DateTime)value.Value, DateFormatHandling.IsoDateFormat, null, CultureInfo.InvariantCulture); } a = stringWriter.ToString(); } break; } case JTokenType.Bytes: a = Convert.ToBase64String((byte[])value.Value); break; case JTokenType.Guid: case JTokenType.TimeSpan: a = value.Value.ToString(); break; case JTokenType.Uri: a = ((Uri)value.Value).OriginalString; break; default: return false; } return string.Equals(a, b, StringComparison.Ordinal); } internal static bool EqualsWithStrictMatch(JValue value, JValue queryValue) { if ((value.Type == JTokenType.Integer && queryValue.Type == JTokenType.Float) || (value.Type == JTokenType.Float && queryValue.Type == JTokenType.Integer)) { return JValue.Compare(value.Type, value.Value, queryValue.Value) == 0; } if (value.Type != queryValue.Type) { return false; } return value.Equals(queryValue); } } internal class QueryFilter : PathFilter { internal QueryExpression Expression; public QueryFilter(QueryExpression expression) { Expression = expression; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { foreach (JToken item2 in (IEnumerable)item) { if (Expression.IsMatch(root, item2, settings)) { yield return item2; } } } } } internal class QueryScanFilter : PathFilter { internal QueryExpression Expression; public QueryScanFilter(QueryExpression expression) { Expression = expression; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken item in current) { if (item is JContainer jContainer) { foreach (JToken item2 in jContainer.DescendantsAndSelf()) { if (Expression.IsMatch(root, item2, settings)) { yield return item2; } } } else if (Expression.IsMatch(root, item, settings)) { yield return item; } } } } internal class RootFilter : PathFilter { public static readonly RootFilter Instance = new RootFilter(); private RootFilter() { } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { return new JToken[1] { root }; } } internal class ScanFilter : PathFilter { internal string? Name; public ScanFilter(string? name) { Name = name; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken c in current) { if (Name == null) { yield return c; } JToken value = c; while (true) { JContainer container = value as JContainer; value = PathFilter.GetNextScanValue(c, container, value); if (value == null) { break; } if (value is JProperty jProperty) { if (jProperty.Name == Name) { yield return jProperty.Value; } } else if (Name == null) { yield return value; } } } } } internal class ScanMultipleFilter : PathFilter { private List _names; public ScanMultipleFilter(List names) { _names = names; } public override IEnumerable ExecuteFilter(JToken root, IEnumerable current, JsonSelectSettings? settings) { foreach (JToken c in current) { JToken value = c; while (true) { JContainer container = value as JContainer; value = PathFilter.GetNextScanValue(c, container, value); if (value == null) { break; } if (!(value is JProperty property)) { continue; } foreach (string name in _names) { if (property.Name == name) { yield return property.Value; } } } } } } } namespace Newtonsoft.Json.Converters { internal class BinaryConverter : JsonConverter { private const string BinaryTypeName = "System.Data.Linq.Binary"; private const string BinaryToArrayName = "ToArray"; private static ReflectionObject? _reflectionObject; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } byte[] byteArray = GetByteArray(value); writer.WriteValue(byteArray); } private byte[] GetByteArray(object value) { if (value.GetType().FullName == "System.Data.Linq.Binary") { EnsureReflectionObject(value.GetType()); return (byte[])_reflectionObject.GetValue(value, "ToArray"); } if (value is SqlBinary sqlBinary) { return sqlBinary.Value; } throw new JsonSerializationException("Unexpected value type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, value.GetType())); } private static void EnsureReflectionObject(Type t) { if (_reflectionObject == null) { _reflectionObject = ReflectionObject.Create(t, t.GetConstructor(new Type[1] { typeof(byte[]) }), "ToArray"); } } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { if (!ReflectionUtils.IsNullable(objectType)) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } byte[] array; if (reader.TokenType == JsonToken.StartArray) { array = ReadByteArray(reader); } else { if (reader.TokenType != JsonToken.String) { throw JsonSerializationException.Create(reader, "Unexpected token parsing binary. Expected String or StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } array = Convert.FromBase64String(reader.Value.ToString()); } Type type = (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType); if (type.FullName == "System.Data.Linq.Binary") { EnsureReflectionObject(type); return _reflectionObject.Creator(array); } if (type == typeof(SqlBinary)) { return new SqlBinary(array); } throw JsonSerializationException.Create(reader, "Unexpected object type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, objectType)); } private byte[] ReadByteArray(JsonReader reader) { List list = new List(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.Integer: list.Add(Convert.ToByte(reader.Value, CultureInfo.InvariantCulture)); break; case JsonToken.EndArray: return list.ToArray(); default: throw JsonSerializationException.Create(reader, "Unexpected token when reading bytes: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); case JsonToken.Comment: break; } } throw JsonSerializationException.Create(reader, "Unexpected end when reading bytes."); } public override bool CanConvert(Type objectType) { if (objectType.FullName == "System.Data.Linq.Binary") { return true; } if (objectType == typeof(SqlBinary) || objectType == typeof(SqlBinary?)) { return true; } return false; } } [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] internal class BsonObjectIdConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { BsonObjectId bsonObjectId = (BsonObjectId)value; if (writer is BsonWriter bsonWriter) { bsonWriter.WriteObjectId(bsonObjectId.Value); } else { writer.WriteValue(bsonObjectId.Value); } } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType != JsonToken.Bytes) { throw new JsonSerializationException("Expected Bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } return new BsonObjectId((byte[])reader.Value); } public override bool CanConvert(Type objectType) { return objectType == typeof(BsonObjectId); } } internal abstract class CustomCreationConverter : JsonConverter { public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { throw new NotSupportedException("CustomCreationConverter should only be used while deserializing."); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } T val = Create(objectType); if (val == null) { throw new JsonSerializationException("No object created."); } serializer.Populate(reader, val); return val; } public abstract T Create(Type objectType); public override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } internal class DataSetConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } DataSet obj = (DataSet)value; DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; DataTableConverter dataTableConverter = new DataTableConverter(); writer.WriteStartObject(); foreach (DataTable table in obj.Tables) { writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName(table.TableName) : table.TableName); dataTableConverter.WriteJson(writer, table, serializer); } writer.WriteEndObject(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } DataSet dataSet = ((objectType == typeof(DataSet)) ? new DataSet() : ((DataSet)Activator.CreateInstance(objectType))); DataTableConverter dataTableConverter = new DataTableConverter(); reader.ReadAndAssert(); while (reader.TokenType == JsonToken.PropertyName) { DataTable dataTable = dataSet.Tables[(string)reader.Value]; bool num = dataTable != null; dataTable = (DataTable)dataTableConverter.ReadJson(reader, typeof(DataTable), dataTable, serializer); if (!num) { dataSet.Tables.Add(dataTable); } reader.ReadAndAssert(); } return dataSet; } public override bool CanConvert(Type valueType) { return typeof(DataSet).IsAssignableFrom(valueType); } } internal class DataTableConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } DataTable obj = (DataTable)value; DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartArray(); foreach (DataRow row in obj.Rows) { writer.WriteStartObject(); foreach (DataColumn column in row.Table.Columns) { object obj2 = row[column]; if (serializer.NullValueHandling != NullValueHandling.Ignore || (obj2 != null && obj2 != DBNull.Value)) { writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName(column.ColumnName) : column.ColumnName); serializer.Serialize(writer, obj2); } } writer.WriteEndObject(); } writer.WriteEndArray(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } DataTable dataTable = existingValue as DataTable; if (dataTable == null) { dataTable = ((objectType == typeof(DataTable)) ? new DataTable() : ((DataTable)Activator.CreateInstance(objectType))); } if (reader.TokenType == JsonToken.PropertyName) { dataTable.TableName = (string)reader.Value; reader.ReadAndAssert(); if (reader.TokenType == JsonToken.Null) { return dataTable; } } if (reader.TokenType != JsonToken.StartArray) { throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable. Expected StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } reader.ReadAndAssert(); while (reader.TokenType != JsonToken.EndArray) { CreateRow(reader, dataTable, serializer); reader.ReadAndAssert(); } return dataTable; } private static void CreateRow(JsonReader reader, DataTable dt, JsonSerializer serializer) { DataRow dataRow = dt.NewRow(); reader.ReadAndAssert(); while (reader.TokenType == JsonToken.PropertyName) { string text = (string)reader.Value; reader.ReadAndAssert(); DataColumn dataColumn = dt.Columns[text]; if (dataColumn == null) { Type columnDataType = GetColumnDataType(reader); dataColumn = new DataColumn(text, columnDataType); dt.Columns.Add(dataColumn); } if (dataColumn.DataType == typeof(DataTable)) { if (reader.TokenType == JsonToken.StartArray) { reader.ReadAndAssert(); } DataTable dataTable = new DataTable(); while (reader.TokenType != JsonToken.EndArray) { CreateRow(reader, dataTable, serializer); reader.ReadAndAssert(); } dataRow[text] = dataTable; } else if (dataColumn.DataType.IsArray && dataColumn.DataType != typeof(byte[])) { if (reader.TokenType == JsonToken.StartArray) { reader.ReadAndAssert(); } List list = new List(); while (reader.TokenType != JsonToken.EndArray) { list.Add(reader.Value); reader.ReadAndAssert(); } Array array = Array.CreateInstance(dataColumn.DataType.GetElementType(), list.Count); ((ICollection)list).CopyTo(array, 0); dataRow[text] = array; } else { object value = ((reader.Value != null) ? (serializer.Deserialize(reader, dataColumn.DataType) ?? DBNull.Value) : DBNull.Value); dataRow[text] = value; } reader.ReadAndAssert(); } dataRow.EndEdit(); dt.Rows.Add(dataRow); } private static Type GetColumnDataType(JsonReader reader) { JsonToken tokenType = reader.TokenType; switch (tokenType) { case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: return reader.ValueType; case JsonToken.Null: case JsonToken.Undefined: case JsonToken.EndArray: return typeof(string); case JsonToken.StartArray: reader.ReadAndAssert(); if (reader.TokenType == JsonToken.StartObject) { return typeof(DataTable); } return GetColumnDataType(reader).MakeArrayType(); default: throw JsonSerializationException.Create(reader, "Unexpected JSON token when reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType)); } } public override bool CanConvert(Type valueType) { return typeof(DataTable).IsAssignableFrom(valueType); } } internal abstract class DateTimeConverterBase : JsonConverter { public override bool CanConvert(Type objectType) { if (objectType == typeof(DateTime) || objectType == typeof(DateTime?)) { return true; } if (objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?)) { return true; } return false; } } internal class DiscriminatedUnionConverter : JsonConverter { internal class Union { public readonly FSharpFunction TagReader; public readonly List Cases; public Union(FSharpFunction tagReader, List cases) { TagReader = tagReader; Cases = cases; } } internal class UnionCase { public readonly int Tag; public readonly string Name; public readonly PropertyInfo[] Fields; public readonly FSharpFunction FieldReader; public readonly FSharpFunction Constructor; public UnionCase(int tag, string name, PropertyInfo[] fields, FSharpFunction fieldReader, FSharpFunction constructor) { Tag = tag; Name = name; Fields = fields; FieldReader = fieldReader; Constructor = constructor; } } private const string CasePropertyName = "Case"; private const string FieldsPropertyName = "Fields"; private static readonly ThreadSafeStore UnionCache = new ThreadSafeStore(CreateUnion); private static readonly ThreadSafeStore UnionTypeLookupCache = new ThreadSafeStore(CreateUnionTypeLookup); private static Type CreateUnionTypeLookup(Type t) { object arg = ((object[])FSharpUtils.Instance.GetUnionCases(null, t, null)).First(); return (Type)FSharpUtils.Instance.GetUnionCaseInfoDeclaringType(arg); } private static Union CreateUnion(Type t) { Union union = new Union((FSharpFunction)FSharpUtils.Instance.PreComputeUnionTagReader(null, t, null), new List()); object[] array = (object[])FSharpUtils.Instance.GetUnionCases(null, t, null); foreach (object obj in array) { UnionCase item = new UnionCase((int)FSharpUtils.Instance.GetUnionCaseInfoTag(obj), (string)FSharpUtils.Instance.GetUnionCaseInfoName(obj), (PropertyInfo[])FSharpUtils.Instance.GetUnionCaseInfoFields(obj), (FSharpFunction)FSharpUtils.Instance.PreComputeUnionReader(null, obj, null), (FSharpFunction)FSharpUtils.Instance.PreComputeUnionConstructor(null, obj, null)); union.Cases.Add(item); } return union; } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; Type key = UnionTypeLookupCache.Get(value.GetType()); Union union = UnionCache.Get(key); int tag = (int)union.TagReader.Invoke(value); UnionCase unionCase = union.Cases.Single((UnionCase c) => c.Tag == tag); writer.WriteStartObject(); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Case") : "Case"); writer.WriteValue(unionCase.Name); if (unionCase.Fields != null && unionCase.Fields.Length != 0) { object[] obj = (object[])unionCase.FieldReader.Invoke(value); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Fields") : "Fields"); writer.WriteStartArray(); object[] array = obj; foreach (object value2 in array) { serializer.Serialize(writer, value2); } writer.WriteEndArray(); } writer.WriteEndObject(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } UnionCase unionCase = null; string caseName = null; JArray jArray = null; reader.ReadAndAssert(); while (reader.TokenType == JsonToken.PropertyName) { string text = reader.Value.ToString(); if (string.Equals(text, "Case", StringComparison.OrdinalIgnoreCase)) { reader.ReadAndAssert(); Union union = UnionCache.Get(objectType); caseName = reader.Value.ToString(); unionCase = union.Cases.SingleOrDefault((UnionCase c) => c.Name == caseName); if (unionCase == null) { throw JsonSerializationException.Create(reader, "No union type found with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName)); } } else { if (!string.Equals(text, "Fields", StringComparison.OrdinalIgnoreCase)) { throw JsonSerializationException.Create(reader, "Unexpected property '{0}' found when reading union.".FormatWith(CultureInfo.InvariantCulture, text)); } reader.ReadAndAssert(); if (reader.TokenType != JsonToken.StartArray) { throw JsonSerializationException.Create(reader, "Union fields must been an array."); } jArray = (JArray)JToken.ReadFrom(reader); } reader.ReadAndAssert(); } if (unionCase == null) { throw JsonSerializationException.Create(reader, "No '{0}' property with union name found.".FormatWith(CultureInfo.InvariantCulture, "Case")); } object[] array = new object[unionCase.Fields.Length]; if (unionCase.Fields.Length != 0 && jArray == null) { throw JsonSerializationException.Create(reader, "No '{0}' property with union fields found.".FormatWith(CultureInfo.InvariantCulture, "Fields")); } if (jArray != null) { if (unionCase.Fields.Length != jArray.Count) { throw JsonSerializationException.Create(reader, "The number of field values does not match the number of properties defined by union '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName)); } for (int i = 0; i < jArray.Count; i++) { JToken jToken = jArray[i]; PropertyInfo propertyInfo = unionCase.Fields[i]; array[i] = jToken.ToObject(propertyInfo.PropertyType, serializer); } } object[] args = new object[1] { array }; return unionCase.Constructor.Invoke(args); } public override bool CanConvert(Type objectType) { if (typeof(IEnumerable).IsAssignableFrom(objectType)) { return false; } object[] customAttributes = objectType.GetCustomAttributes(inherit: true); bool flag = false; object[] array = customAttributes; for (int i = 0; i < array.Length; i++) { Type type = array[i].GetType(); if (type.FullName == "Microsoft.FSharp.Core.CompilationMappingAttribute") { FSharpUtils.EnsureInitialized(type.Assembly()); flag = true; break; } } if (!flag) { return false; } return (bool)FSharpUtils.Instance.IsUnion(null, objectType, null); } } internal class EntityKeyMemberConverter : JsonConverter { private const string EntityKeyMemberFullTypeName = "System.Data.EntityKeyMember"; private const string KeyPropertyName = "Key"; private const string TypePropertyName = "Type"; private const string ValuePropertyName = "Value"; private static ReflectionObject? _reflectionObject; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } EnsureReflectionObject(value.GetType()); DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; string value2 = (string)_reflectionObject.GetValue(value, "Key"); object value3 = _reflectionObject.GetValue(value, "Value"); Type type = value3?.GetType(); writer.WriteStartObject(); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Key") : "Key"); writer.WriteValue(value2); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Type") : "Type"); writer.WriteValue(type?.FullName); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Value") : "Value"); if (type != null) { if (JsonSerializerInternalWriter.TryConvertToString(value3, type, out string s)) { writer.WriteValue(s); } else { writer.WriteValue(value3); } } else { writer.WriteNull(); } writer.WriteEndObject(); } private static void ReadAndAssertProperty(JsonReader reader, string propertyName) { reader.ReadAndAssert(); if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value?.ToString(), propertyName, StringComparison.OrdinalIgnoreCase)) { throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName)); } } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { EnsureReflectionObject(objectType); object obj = _reflectionObject.Creator(); ReadAndAssertProperty(reader, "Key"); reader.ReadAndAssert(); _reflectionObject.SetValue(obj, "Key", reader.Value?.ToString()); ReadAndAssertProperty(reader, "Type"); reader.ReadAndAssert(); Type type = Type.GetType(reader.Value?.ToString()); ReadAndAssertProperty(reader, "Value"); reader.ReadAndAssert(); _reflectionObject.SetValue(obj, "Value", serializer.Deserialize(reader, type)); reader.ReadAndAssert(); return obj; } private static void EnsureReflectionObject(Type objectType) { if (_reflectionObject == null) { _reflectionObject = ReflectionObject.Create(objectType, "Key", "Value"); } } public override bool CanConvert(Type objectType) { return objectType.AssignableToTypeName("System.Data.EntityKeyMember", searchInterfaces: false); } } internal class ExpandoObjectConverter : JsonConverter { public override bool CanWrite => false; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { return ReadValue(reader); } private object? ReadValue(JsonReader reader) { if (!reader.MoveToContent()) { throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); } switch (reader.TokenType) { case JsonToken.StartObject: return ReadObject(reader); case JsonToken.StartArray: return ReadList(reader); default: if (JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) { return reader.Value; } throw JsonSerializationException.Create(reader, "Unexpected token when converting ExpandoObject: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } private object ReadList(JsonReader reader) { IList list = new List(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.EndArray: return list; case JsonToken.Comment: continue; } object item = ReadValue(reader); list.Add(item); } throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); } private object ReadObject(JsonReader reader) { IDictionary dictionary = new ExpandoObject(); while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: { string key = reader.Value.ToString(); if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); } object value = ReadValue(reader); dictionary[key] = value; break; } case JsonToken.EndObject: return dictionary; } } throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject."); } public override bool CanConvert(Type objectType) { return objectType == typeof(ExpandoObject); } } internal class IsoDateTimeConverter : DateTimeConverterBase { private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; private string? _dateTimeFormat; private CultureInfo? _culture; public DateTimeStyles DateTimeStyles { get { return _dateTimeStyles; } set { _dateTimeStyles = value; } } public string? DateTimeFormat { get { return _dateTimeFormat ?? string.Empty; } set { _dateTimeFormat = (StringUtils.IsNullOrEmpty(value) ? null : value); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.CurrentCulture; } set { _culture = value; } } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { string value2; if (value is DateTime dateTime) { if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) { dateTime = dateTime.ToUniversalTime(); } value2 = dateTime.ToString(_dateTimeFormat ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK", Culture); } else { if (!(value is DateTimeOffset dateTimeOffset)) { throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value))); } if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) { dateTimeOffset = dateTimeOffset.ToUniversalTime(); } value2 = dateTimeOffset.ToString(_dateTimeFormat ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK", Culture); } writer.WriteValue(value2); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = ReflectionUtils.IsNullableType(objectType); if (reader.TokenType == JsonToken.Null) { if (!flag) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } Type type = (flag ? Nullable.GetUnderlyingType(objectType) : objectType); if (reader.TokenType == JsonToken.Date) { if (type == typeof(DateTimeOffset)) { if (!(reader.Value is DateTimeOffset)) { return new DateTimeOffset((DateTime)reader.Value); } return reader.Value; } if (reader.Value is DateTimeOffset dateTimeOffset) { return dateTimeOffset.DateTime; } return reader.Value; } if (reader.TokenType != JsonToken.String) { throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } string text = reader.Value?.ToString(); if (StringUtils.IsNullOrEmpty(text) && flag) { return null; } if (type == typeof(DateTimeOffset)) { if (!StringUtils.IsNullOrEmpty(_dateTimeFormat)) { return DateTimeOffset.ParseExact(text, _dateTimeFormat, Culture, _dateTimeStyles); } return DateTimeOffset.Parse(text, Culture, _dateTimeStyles); } if (!StringUtils.IsNullOrEmpty(_dateTimeFormat)) { return DateTime.ParseExact(text, _dateTimeFormat, Culture, _dateTimeStyles); } return DateTime.Parse(text, Culture, _dateTimeStyles); } } internal class JavaScriptDateTimeConverter : DateTimeConverterBase { public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { long value2; if (value is DateTime dateTime) { value2 = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTime.ToUniversalTime()); } else { if (!(value is DateTimeOffset dateTimeOffset)) { throw new JsonSerializationException("Expected date object value."); } value2 = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTimeOffset.ToUniversalTime().UtcDateTime); } writer.WriteStartConstructor("Date"); writer.WriteValue(value2); writer.WriteEndConstructor(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { if (!ReflectionUtils.IsNullable(objectType)) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value?.ToString(), "Date", StringComparison.Ordinal)) { throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value)); } if (!JavaScriptUtils.TryGetDateFromConstructorJson(reader, out DateTime dateTime, out string errorMessage)) { throw JsonSerializationException.Create(reader, errorMessage); } if ((ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType) == typeof(DateTimeOffset)) { return new DateTimeOffset(dateTime); } return dateTime; } } internal class KeyValuePairConverter : JsonConverter { private const string KeyName = "Key"; private const string ValueName = "Value"; private static readonly ThreadSafeStore ReflectionObjectPerType = new ThreadSafeStore(InitializeReflectionObject); private static ReflectionObject InitializeReflectionObject(Type t) { Type[] genericArguments = t.GetGenericArguments(); Type type = ((IList)genericArguments)[0]; Type type2 = ((IList)genericArguments)[1]; return ReflectionObject.Create(t, t.GetConstructor(new Type[2] { type, type2 }), "Key", "Value"); } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } ReflectionObject reflectionObject = ReflectionObjectPerType.Get(value.GetType()); DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartObject(); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Key") : "Key"); serializer.Serialize(writer, reflectionObject.GetValue(value, "Key"), reflectionObject.GetType("Key")); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Value") : "Value"); serializer.Serialize(writer, reflectionObject.GetValue(value, "Value"), reflectionObject.GetType("Value")); writer.WriteEndObject(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { if (!ReflectionUtils.IsNullableType(objectType)) { throw JsonSerializationException.Create(reader, "Cannot convert null value to KeyValuePair."); } return null; } object obj = null; object obj2 = null; reader.ReadAndAssert(); Type key = (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType); ReflectionObject reflectionObject = ReflectionObjectPerType.Get(key); JsonContract jsonContract = serializer.ContractResolver.ResolveContract(reflectionObject.GetType("Key")); JsonContract jsonContract2 = serializer.ContractResolver.ResolveContract(reflectionObject.GetType("Value")); while (reader.TokenType == JsonToken.PropertyName) { string a = reader.Value.ToString(); if (string.Equals(a, "Key", StringComparison.OrdinalIgnoreCase)) { reader.ReadForTypeAndAssert(jsonContract, hasConverter: false); obj = serializer.Deserialize(reader, jsonContract.UnderlyingType); } else if (string.Equals(a, "Value", StringComparison.OrdinalIgnoreCase)) { reader.ReadForTypeAndAssert(jsonContract2, hasConverter: false); obj2 = serializer.Deserialize(reader, jsonContract2.UnderlyingType); } else { reader.Skip(); } reader.ReadAndAssert(); } return reflectionObject.Creator(obj, obj2); } public override bool CanConvert(Type objectType) { Type type = (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType); if (type.IsValueType() && type.IsGenericType()) { return type.GetGenericTypeDefinition() == typeof(KeyValuePair<, >); } return false; } } internal class RegexConverter : JsonConverter { private const string PatternName = "Pattern"; private const string OptionsName = "Options"; public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } Regex regex = (Regex)value; if (writer is BsonWriter writer2) { WriteBson(writer2, regex); } else { WriteJson(writer, regex, serializer); } } private bool HasFlag(RegexOptions options, RegexOptions flag) { return (options & flag) == flag; } private void WriteBson(BsonWriter writer, Regex regex) { string text = null; if (HasFlag(regex.Options, RegexOptions.IgnoreCase)) { text += "i"; } if (HasFlag(regex.Options, RegexOptions.Multiline)) { text += "m"; } if (HasFlag(regex.Options, RegexOptions.Singleline)) { text += "s"; } text += "u"; if (HasFlag(regex.Options, RegexOptions.ExplicitCapture)) { text += "x"; } writer.WriteRegex(regex.ToString(), text); } private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer) { DefaultContractResolver defaultContractResolver = serializer.ContractResolver as DefaultContractResolver; writer.WriteStartObject(); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Pattern") : "Pattern"); writer.WriteValue(regex.ToString()); writer.WritePropertyName((defaultContractResolver != null) ? defaultContractResolver.GetResolvedPropertyName("Options") : "Options"); serializer.Serialize(writer, regex.Options); writer.WriteEndObject(); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { return reader.TokenType switch { JsonToken.StartObject => ReadRegexObject(reader, serializer), JsonToken.String => ReadRegexString(reader), JsonToken.Null => null, _ => throw JsonSerializationException.Create(reader, "Unexpected token when reading Regex."), }; } private object ReadRegexString(JsonReader reader) { string text = (string)reader.Value; if (text.Length > 0 && text[0] == '/') { int num = text.LastIndexOf('/'); if (num > 0) { string pattern = text.Substring(1, num - 1); RegexOptions regexOptions = MiscellaneousUtils.GetRegexOptions(text.Substring(num + 1)); return new Regex(pattern, regexOptions); } } throw JsonSerializationException.Create(reader, "Regex pattern must be enclosed by slashes."); } private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer) { string text = null; RegexOptions? regexOptions = null; while (reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: { string a = reader.Value.ToString(); if (!reader.Read()) { throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex."); } if (string.Equals(a, "Pattern", StringComparison.OrdinalIgnoreCase)) { text = (string)reader.Value; } else if (string.Equals(a, "Options", StringComparison.OrdinalIgnoreCase)) { regexOptions = serializer.Deserialize(reader); } else { reader.Skip(); } break; } case JsonToken.EndObject: if (text == null) { throw JsonSerializationException.Create(reader, "Error deserializing Regex. No pattern found."); } return new Regex(text, regexOptions.GetValueOrDefault()); } } throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex."); } public override bool CanConvert(Type objectType) { if (objectType.Name == "Regex") { return IsRegex(objectType); } return false; } [MethodImpl(MethodImplOptions.NoInlining)] private bool IsRegex(Type objectType) { return objectType == typeof(Regex); } } internal class StringEnumConverter : JsonConverter { [Obsolete("StringEnumConverter.CamelCaseText is obsolete. Set StringEnumConverter.NamingStrategy with CamelCaseNamingStrategy instead.")] public bool CamelCaseText { get { if (!(NamingStrategy is CamelCaseNamingStrategy)) { return false; } return true; } set { if (value) { if (!(NamingStrategy is CamelCaseNamingStrategy)) { NamingStrategy = new CamelCaseNamingStrategy(); } } else if (NamingStrategy is CamelCaseNamingStrategy) { NamingStrategy = null; } } } public NamingStrategy? NamingStrategy { get; set; } public bool AllowIntegerValues { get; set; } = true; public StringEnumConverter() { } [Obsolete("StringEnumConverter(bool) is obsolete. Create a converter with StringEnumConverter(NamingStrategy, bool) instead.")] public StringEnumConverter(bool camelCaseText) { if (camelCaseText) { NamingStrategy = new CamelCaseNamingStrategy(); } } public StringEnumConverter(NamingStrategy namingStrategy, bool allowIntegerValues = true) { NamingStrategy = namingStrategy; AllowIntegerValues = allowIntegerValues; } public StringEnumConverter(Type namingStrategyType) { ValidationUtils.ArgumentNotNull(namingStrategyType, "namingStrategyType"); NamingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(namingStrategyType, null); } public StringEnumConverter(Type namingStrategyType, object[] namingStrategyParameters) { ValidationUtils.ArgumentNotNull(namingStrategyType, "namingStrategyType"); NamingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(namingStrategyType, namingStrategyParameters); } public StringEnumConverter(Type namingStrategyType, object[] namingStrategyParameters, bool allowIntegerValues) { ValidationUtils.ArgumentNotNull(namingStrategyType, "namingStrategyType"); NamingStrategy = JsonTypeReflector.CreateNamingStrategyInstance(namingStrategyType, namingStrategyParameters); AllowIntegerValues = allowIntegerValues; } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } Enum @enum = (Enum)value; if (!EnumUtils.TryToString(@enum.GetType(), value, NamingStrategy, out string name)) { if (!AllowIntegerValues) { throw JsonSerializationException.Create(null, writer.ContainerPath, "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, @enum.ToString("D")), null); } writer.WriteValue(value); } else { writer.WriteValue(name); } } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { if (!ReflectionUtils.IsNullableType(objectType)) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } bool flag = ReflectionUtils.IsNullableType(objectType); Type type = (flag ? Nullable.GetUnderlyingType(objectType) : objectType); try { if (reader.TokenType == JsonToken.String) { string value = reader.Value?.ToString(); if (StringUtils.IsNullOrEmpty(value) && flag) { return null; } return EnumUtils.ParseEnum(type, NamingStrategy, value, !AllowIntegerValues); } if (reader.TokenType == JsonToken.Integer) { if (!AllowIntegerValues) { throw JsonSerializationException.Create(reader, "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, reader.Value)); } return ConvertUtils.ConvertOrCast(reader.Value, CultureInfo.InvariantCulture, type); } } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(reader.Value), objectType), ex); } throw JsonSerializationException.Create(reader, "Unexpected token {0} when parsing enum.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } public override bool CanConvert(Type objectType) { return (ReflectionUtils.IsNullableType(objectType) ? Nullable.GetUnderlyingType(objectType) : objectType).IsEnum(); } } internal class UnixDateTimeConverter : DateTimeConverterBase { internal static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); public bool AllowPreEpoch { get; set; } public UnixDateTimeConverter() : this(allowPreEpoch: false) { } public UnixDateTimeConverter(bool allowPreEpoch) { AllowPreEpoch = allowPreEpoch; } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { long num; if (value is DateTime dateTime) { num = (long)(dateTime.ToUniversalTime() - UnixEpoch).TotalSeconds; } else { if (!(value is DateTimeOffset dateTimeOffset)) { throw new JsonSerializationException("Expected date object value."); } num = (long)(dateTimeOffset.ToUniversalTime() - UnixEpoch).TotalSeconds; } if (!AllowPreEpoch && num < 0) { throw new JsonSerializationException("Cannot convert date value that is before Unix epoch of 00:00:00 UTC on 1 January 1970."); } writer.WriteValue(num); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { bool flag = ReflectionUtils.IsNullable(objectType); if (reader.TokenType == JsonToken.Null) { if (!flag) { throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } return null; } long result; if (reader.TokenType == JsonToken.Integer) { result = (long)reader.Value; } else { if (reader.TokenType != JsonToken.String) { throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected Integer or String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } if (!long.TryParse((string)reader.Value, out result)) { throw JsonSerializationException.Create(reader, "Cannot convert invalid value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } } if (AllowPreEpoch || result >= 0) { DateTime unixEpoch = UnixEpoch; DateTime dateTime = unixEpoch.AddSeconds(result); if ((flag ? Nullable.GetUnderlyingType(objectType) : objectType) == typeof(DateTimeOffset)) { return new DateTimeOffset(dateTime, TimeSpan.Zero); } return dateTime; } throw JsonSerializationException.Create(reader, "Cannot convert value that is before Unix epoch of 00:00:00 UTC on 1 January 1970 to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType)); } } internal class VersionConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } if (value is Version) { writer.WriteValue(value.ToString()); return; } throw new JsonSerializationException("Expected Version object value"); } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { if (reader.TokenType == JsonToken.Null) { return null; } if (reader.TokenType == JsonToken.String) { try { return new Version((string)reader.Value); } catch (Exception ex) { throw JsonSerializationException.Create(reader, "Error parsing version string: {0}".FormatWith(CultureInfo.InvariantCulture, reader.Value), ex); } } throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing version. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value)); } public override bool CanConvert(Type objectType) { return objectType == typeof(Version); } } internal class XmlDocumentWrapper : XmlNodeWrapper, IXmlDocument, IXmlNode { private readonly XmlDocument _document; public IXmlElement? DocumentElement { get { if (_document.DocumentElement == null) { return null; } return new XmlElementWrapper(_document.DocumentElement); } } public XmlDocumentWrapper(XmlDocument document) : base(document) { _document = document; } public IXmlNode CreateComment(string? data) { return new XmlNodeWrapper(_document.CreateComment(data)); } public IXmlNode CreateTextNode(string? text) { return new XmlNodeWrapper(_document.CreateTextNode(text)); } public IXmlNode CreateCDataSection(string? data) { return new XmlNodeWrapper(_document.CreateCDataSection(data)); } public IXmlNode CreateWhitespace(string? text) { return new XmlNodeWrapper(_document.CreateWhitespace(text)); } public IXmlNode CreateSignificantWhitespace(string? text) { return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text)); } public IXmlNode CreateXmlDeclaration(string version, string? encoding, string? standalone) { return new XmlDeclarationWrapper(_document.CreateXmlDeclaration(version, encoding, standalone)); } public IXmlNode CreateXmlDocumentType(string name, string? publicId, string? systemId, string? internalSubset) { return new XmlDocumentTypeWrapper(_document.CreateDocumentType(name, publicId, systemId, null)); } public IXmlNode CreateProcessingInstruction(string target, string data) { return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data)); } public IXmlElement CreateElement(string elementName) { return new XmlElementWrapper(_document.CreateElement(elementName)); } public IXmlElement CreateElement(string qualifiedName, string namespaceUri) { return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceUri)); } public IXmlNode CreateAttribute(string name, string? value) { return new XmlNodeWrapper(_document.CreateAttribute(name)) { Value = value }; } public IXmlNode CreateAttribute(string qualifiedName, string? namespaceUri, string? value) { return new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri)) { Value = value }; } } internal class XmlElementWrapper : XmlNodeWrapper, IXmlElement, IXmlNode { private readonly XmlElement _element; public bool IsEmpty => _element.IsEmpty; public XmlElementWrapper(XmlElement element) : base(element) { _element = element; } public void SetAttributeNode(IXmlNode attribute) { XmlNodeWrapper xmlNodeWrapper = (XmlNodeWrapper)attribute; _element.SetAttributeNode((XmlAttribute)xmlNodeWrapper.WrappedNode); } public string? GetPrefixOfNamespace(string namespaceUri) { return _element.GetPrefixOfNamespace(namespaceUri); } } internal class XmlDeclarationWrapper : XmlNodeWrapper, IXmlDeclaration, IXmlNode { private readonly XmlDeclaration _declaration; public string? Version => _declaration.Version; public string? Encoding { get { return _declaration.Encoding; } set { _declaration.Encoding = value; } } public string? Standalone { get { return _declaration.Standalone; } set { _declaration.Standalone = value; } } public XmlDeclarationWrapper(XmlDeclaration declaration) : base(declaration) { _declaration = declaration; } } internal class XmlDocumentTypeWrapper : XmlNodeWrapper, IXmlDocumentType, IXmlNode { private readonly XmlDocumentType _documentType; public string Name => _documentType.Name; public string? System => _documentType.SystemId; public string? Public => _documentType.PublicId; public string? InternalSubset => _documentType.InternalSubset; public override string? LocalName => "DOCTYPE"; public XmlDocumentTypeWrapper(XmlDocumentType documentType) : base(documentType) { _documentType = documentType; } } internal class XmlNodeWrapper : IXmlNode { private readonly XmlNode _node; private List? _childNodes; private List? _attributes; public object? WrappedNode => _node; public XmlNodeType NodeType => _node.NodeType; public virtual string? LocalName => _node.LocalName; public List ChildNodes { get { if (_childNodes == null) { if (!_node.HasChildNodes) { _childNodes = XmlNodeConverter.EmptyChildNodes; } else { _childNodes = new List(_node.ChildNodes.Count); foreach (XmlNode childNode in _node.ChildNodes) { _childNodes.Add(WrapNode(childNode)); } } } return _childNodes; } } protected virtual bool HasChildNodes => _node.HasChildNodes; public List Attributes { get { if (_attributes == null) { if (!HasAttributes) { _attributes = XmlNodeConverter.EmptyChildNodes; } else { _attributes = new List(_node.Attributes.Count); foreach (XmlAttribute attribute in _node.Attributes) { _attributes.Add(WrapNode(attribute)); } } } return _attributes; } } private bool HasAttributes { get { if (_node is XmlElement xmlElement) { return xmlElement.HasAttributes; } XmlAttributeCollection? attributes = _node.Attributes; if (attributes == null) { return false; } return attributes.Count > 0; } } public IXmlNode? ParentNode { get { XmlNode xmlNode = ((_node is XmlAttribute xmlAttribute) ? xmlAttribute.OwnerElement : _node.ParentNode); if (xmlNode == null) { return null; } return WrapNode(xmlNode); } } public string? Value { get { return _node.Value; } set { _node.Value = value; } } public string? NamespaceUri => _node.NamespaceURI; public XmlNodeWrapper(XmlNode node) { _node = node; } internal static IXmlNode WrapNode(XmlNode node) { return node.NodeType switch { XmlNodeType.Element => new XmlElementWrapper((XmlElement)node), XmlNodeType.XmlDeclaration => new XmlDeclarationWrapper((XmlDeclaration)node), XmlNodeType.DocumentType => new XmlDocumentTypeWrapper((XmlDocumentType)node), _ => new XmlNodeWrapper(node), }; } public IXmlNode AppendChild(IXmlNode newChild) { XmlNodeWrapper xmlNodeWrapper = (XmlNodeWrapper)newChild; _node.AppendChild(xmlNodeWrapper._node); _childNodes = null; _attributes = null; return newChild; } } internal interface IXmlDocument : IXmlNode { IXmlElement? DocumentElement { get; } IXmlNode CreateComment(string? text); IXmlNode CreateTextNode(string? text); IXmlNode CreateCDataSection(string? data); IXmlNode CreateWhitespace(string? text); IXmlNode CreateSignificantWhitespace(string? text); IXmlNode CreateXmlDeclaration(string version, string? encoding, string? standalone); IXmlNode CreateXmlDocumentType(string name, string? publicId, string? systemId, string? internalSubset); IXmlNode CreateProcessingInstruction(string target, string data); IXmlElement CreateElement(string elementName); IXmlElement CreateElement(string qualifiedName, string namespaceUri); IXmlNode CreateAttribute(string name, string value); IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value); } internal interface IXmlDeclaration : IXmlNode { string? Version { get; } string? Encoding { get; set; } string? Standalone { get; set; } } internal interface IXmlDocumentType : IXmlNode { string Name { get; } string? System { get; } string? Public { get; } string? InternalSubset { get; } } internal interface IXmlElement : IXmlNode { bool IsEmpty { get; } void SetAttributeNode(IXmlNode attribute); string? GetPrefixOfNamespace(string namespaceUri); } internal interface IXmlNode { XmlNodeType NodeType { get; } string? LocalName { get; } List ChildNodes { get; } List Attributes { get; } IXmlNode? ParentNode { get; } string? Value { get; set; } string? NamespaceUri { get; } object? WrappedNode { get; } IXmlNode AppendChild(IXmlNode newChild); } internal class XDeclarationWrapper : XObjectWrapper, IXmlDeclaration, IXmlNode { internal XDeclaration Declaration { get; } public override XmlNodeType NodeType => XmlNodeType.XmlDeclaration; public string? Version => Declaration.Version; public string? Encoding { get { return Declaration.Encoding; } set { Declaration.Encoding = value; } } public string? Standalone { get { return Declaration.Standalone; } set { Declaration.Standalone = value; } } public XDeclarationWrapper(XDeclaration declaration) : base(null) { Declaration = declaration; } } internal class XDocumentTypeWrapper : XObjectWrapper, IXmlDocumentType, IXmlNode { private readonly XDocumentType _documentType; public string Name => _documentType.Name; public string? System => _documentType.SystemId; public string? Public => _documentType.PublicId; public string? InternalSubset => _documentType.InternalSubset; public override string? LocalName => "DOCTYPE"; public XDocumentTypeWrapper(XDocumentType documentType) : base((XObject?)(object)documentType) { _documentType = documentType; } } internal class XDocumentWrapper : XContainerWrapper, IXmlDocument, IXmlNode { private XDocument Document => (XDocument)base.WrappedNode; public override List ChildNodes { get { List childNodes = base.ChildNodes; if (Document.Declaration != null && (childNodes.Count == 0 || childNodes[0].NodeType != XmlNodeType.XmlDeclaration)) { childNodes.Insert(0, new XDeclarationWrapper(Document.Declaration)); } return childNodes; } } protected override bool HasChildNodes { get { if (base.HasChildNodes) { return true; } return Document.Declaration != null; } } public IXmlElement? DocumentElement { get { if (Document.Root == null) { return null; } return new XElementWrapper(Document.Root); } } public XDocumentWrapper(XDocument document) : base((XContainer)(object)document) { } public IXmlNode CreateComment(string? text) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown return new XObjectWrapper((XObject?)new XComment(text)); } public IXmlNode CreateTextNode(string? text) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown return new XObjectWrapper((XObject?)new XText(text)); } public IXmlNode CreateCDataSection(string? data) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown return new XObjectWrapper((XObject?)new XCData(data)); } public IXmlNode CreateWhitespace(string? text) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown return new XObjectWrapper((XObject?)new XText(text)); } public IXmlNode CreateSignificantWhitespace(string? text) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown return new XObjectWrapper((XObject?)new XText(text)); } public IXmlNode CreateXmlDeclaration(string version, string? encoding, string? standalone) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone)); } public IXmlNode CreateXmlDocumentType(string name, string? publicId, string? systemId, string? internalSubset) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown return new XDocumentTypeWrapper(new XDocumentType(name, publicId, systemId, internalSubset)); } public IXmlNode CreateProcessingInstruction(string target, string data) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data)); } public IXmlElement CreateElement(string elementName) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown return new XElementWrapper(new XElement(XName.op_Implicit(elementName))); } public IXmlElement CreateElement(string qualifiedName, string namespaceUri) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown return new XElementWrapper(new XElement(XName.Get(MiscellaneousUtils.GetLocalName(qualifiedName), namespaceUri))); } public IXmlNode CreateAttribute(string name, string value) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown return new XAttributeWrapper(new XAttribute(XName.op_Implicit(name), (object)value)); } public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown return new XAttributeWrapper(new XAttribute(XName.Get(MiscellaneousUtils.GetLocalName(qualifiedName), namespaceUri), (object)value)); } public override IXmlNode AppendChild(IXmlNode newChild) { if (newChild is XDeclarationWrapper xDeclarationWrapper) { Document.Declaration = xDeclarationWrapper.Declaration; return xDeclarationWrapper; } return base.AppendChild(newChild); } } internal class XTextWrapper : XObjectWrapper { private XText Text => (XText)base.WrappedNode; public override string? Value { get { return Text.Value; } set { Text.Value = value ?? string.Empty; } } public override IXmlNode? ParentNode { get { if (((XObject)Text).Parent == null) { return null; } return XContainerWrapper.WrapNode((XObject)(object)((XObject)Text).Parent); } } public XTextWrapper(XText text) : base((XObject?)(object)text) { } } internal class XCommentWrapper : XObjectWrapper { private XComment Text => (XComment)base.WrappedNode; public override string? Value { get { return Text.Value; } set { Text.Value = value ?? string.Empty; } } public override IXmlNode? ParentNode { get { if (((XObject)Text).Parent == null) { return null; } return XContainerWrapper.WrapNode((XObject)(object)((XObject)Text).Parent); } } public XCommentWrapper(XComment text) : base((XObject?)(object)text) { } } internal class XProcessingInstructionWrapper : XObjectWrapper { private XProcessingInstruction ProcessingInstruction => (XProcessingInstruction)base.WrappedNode; public override string? LocalName => ProcessingInstruction.Target; public override string? Value { get { return ProcessingInstruction.Data; } set { ProcessingInstruction.Data = value ?? string.Empty; } } public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction) : base((XObject?)(object)processingInstruction) { } } internal class XContainerWrapper : XObjectWrapper { private List? _childNodes; private XContainer Container => (XContainer)base.WrappedNode; public override List ChildNodes { get { if (_childNodes == null) { if (!HasChildNodes) { _childNodes = XmlNodeConverter.EmptyChildNodes; } else { _childNodes = new List(); foreach (XNode item in Container.Nodes()) { _childNodes.Add(WrapNode((XObject)(object)item)); } } } return _childNodes; } } protected virtual bool HasChildNodes => Container.LastNode != null; public override IXmlNode? ParentNode { get { if (((XObject)Container).Parent == null) { return null; } return WrapNode((XObject)(object)((XObject)Container).Parent); } } public XContainerWrapper(XContainer container) : base((XObject?)(object)container) { } internal static IXmlNode WrapNode(XObject node) { XDocument val = (XDocument)(object)((node is XDocument) ? node : null); if (val != null) { return new XDocumentWrapper(val); } XElement val2 = (XElement)(object)((node is XElement) ? node : null); if (val2 != null) { return new XElementWrapper(val2); } XContainer val3 = (XContainer)(object)((node is XContainer) ? node : null); if (val3 != null) { return new XContainerWrapper(val3); } XProcessingInstruction val4 = (XProcessingInstruction)(object)((node is XProcessingInstruction) ? node : null); if (val4 != null) { return new XProcessingInstructionWrapper(val4); } XText val5 = (XText)(object)((node is XText) ? node : null); if (val5 != null) { return new XTextWrapper(val5); } XComment val6 = (XComment)(object)((node is XComment) ? node : null); if (val6 != null) { return new XCommentWrapper(val6); } XAttribute val7 = (XAttribute)(object)((node is XAttribute) ? node : null); if (val7 != null) { return new XAttributeWrapper(val7); } XDocumentType val8 = (XDocumentType)(object)((node is XDocumentType) ? node : null); if (val8 != null) { return new XDocumentTypeWrapper(val8); } return new XObjectWrapper(node); } public override IXmlNode AppendChild(IXmlNode newChild) { Container.Add(newChild.WrappedNode); _childNodes = null; return newChild; } } internal class XObjectWrapper : IXmlNode { private readonly XObject? _xmlObject; public object? WrappedNode => _xmlObject; public virtual XmlNodeType NodeType { get { XObject? xmlObject = _xmlObject; if (xmlObject == null) { return XmlNodeType.None; } return xmlObject.NodeType; } } public virtual string? LocalName => null; public virtual List ChildNodes => XmlNodeConverter.EmptyChildNodes; public virtual List Attributes => XmlNodeConverter.EmptyChildNodes; public virtual IXmlNode? ParentNode => null; public virtual string? Value { get { return null; } set { throw new InvalidOperationException(); } } public virtual string? NamespaceUri => null; public XObjectWrapper(XObject? xmlObject) { _xmlObject = xmlObject; } public virtual IXmlNode AppendChild(IXmlNode newChild) { throw new InvalidOperationException(); } } internal class XAttributeWrapper : XObjectWrapper { private XAttribute Attribute => (XAttribute)base.WrappedNode; public override string? Value { get { return Attribute.Value; } set { Attribute.Value = value ?? string.Empty; } } public override string? LocalName => Attribute.Name.LocalName; public override string? NamespaceUri => Attribute.Name.NamespaceName; public override IXmlNode? ParentNode { get { if (((XObject)Attribute).Parent == null) { return null; } return XContainerWrapper.WrapNode((XObject)(object)((XObject)Attribute).Parent); } } public XAttributeWrapper(XAttribute attribute) : base((XObject?)(object)attribute) { } } internal class XElementWrapper : XContainerWrapper, IXmlElement, IXmlNode { private List? _attributes; private XElement Element => (XElement)base.WrappedNode; public override List Attributes { get { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown if (_attributes == null) { if (!Element.HasAttributes && !HasImplicitNamespaceAttribute(NamespaceUri)) { _attributes = XmlNodeConverter.EmptyChildNodes; } else { _attributes = new List(); foreach (XAttribute item in Element.Attributes()) { _attributes.Add(new XAttributeWrapper(item)); } string namespaceUri = NamespaceUri; if (HasImplicitNamespaceAttribute(namespaceUri)) { _attributes.Insert(0, new XAttributeWrapper(new XAttribute(XName.op_Implicit("xmlns"), (object)namespaceUri))); } } } return _attributes; } } public override string? Value { get { return Element.Value; } set { Element.Value = value ?? string.Empty; } } public override string? LocalName => Element.Name.LocalName; public override string? NamespaceUri => Element.Name.NamespaceName; public bool IsEmpty => Element.IsEmpty; public XElementWrapper(XElement element) : base((XContainer)(object)element) { } public void SetAttributeNode(IXmlNode attribute) { XObjectWrapper xObjectWrapper = (XObjectWrapper)attribute; ((XContainer)Element).Add(xObjectWrapper.WrappedNode); _attributes = null; } private bool HasImplicitNamespaceAttribute(string namespaceUri) { if (!StringUtils.IsNullOrEmpty(namespaceUri) && namespaceUri != ParentNode?.NamespaceUri && StringUtils.IsNullOrEmpty(GetPrefixOfNamespace(namespaceUri))) { bool flag = false; if (Element.HasAttributes) { foreach (XAttribute item in Element.Attributes()) { if (item.Name.LocalName == "xmlns" && StringUtils.IsNullOrEmpty(item.Name.NamespaceName) && item.Value == namespaceUri) { flag = true; } } } if (!flag) { return true; } } return false; } public override IXmlNode AppendChild(IXmlNode newChild) { IXmlNode result = base.AppendChild(newChild); _attributes = null; return result; } public string? GetPrefixOfNamespace(string namespaceUri) { return Element.GetPrefixOfNamespace(XNamespace.op_Implicit(namespaceUri)); } } internal class XmlNodeConverter : JsonConverter { internal static readonly List EmptyChildNodes = new List(); private const string TextName = "#text"; private const string CommentName = "#comment"; private const string CDataName = "#cdata-section"; private const string WhitespaceName = "#whitespace"; private const string SignificantWhitespaceName = "#significant-whitespace"; private const string DeclarationName = "?xml"; private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json"; public string? DeserializeRootElementName { get; set; } public bool WriteArrayAttribute { get; set; } public bool OmitRootObject { get; set; } public bool EncodeSpecialCharacters { get; set; } public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer) { if (value == null) { writer.WriteNull(); return; } IXmlNode node = WrapXml(value); XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); PushParentNamespaces(node, manager); if (!OmitRootObject) { writer.WriteStartObject(); } SerializeNode(writer, node, manager, !OmitRootObject); if (!OmitRootObject) { writer.WriteEndObject(); } } private IXmlNode WrapXml(object value) { XObject val = (XObject)((value is XObject) ? value : null); if (val != null) { return XContainerWrapper.WrapNode(val); } if (value is XmlNode node) { return XmlNodeWrapper.WrapNode(node); } throw new ArgumentException("Value must be an XML object.", "value"); } private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager) { List list = null; IXmlNode xmlNode = node; while ((xmlNode = xmlNode.ParentNode) != null) { if (xmlNode.NodeType == XmlNodeType.Element) { if (list == null) { list = new List(); } list.Add(xmlNode); } } if (list == null) { return; } list.Reverse(); foreach (IXmlNode item in list) { manager.PushScope(); foreach (IXmlNode attribute in item.Attributes) { if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/" && attribute.LocalName != "xmlns") { manager.AddNamespace(attribute.LocalName, attribute.Value); } } } } private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager) { string text = ((node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/")) ? null : manager.LookupPrefix(node.NamespaceUri)); if (!StringUtils.IsNullOrEmpty(text)) { return text + ":" + XmlConvert.DecodeName(node.LocalName); } return XmlConvert.DecodeName(node.LocalName); } private string GetPropertyName(IXmlNode node, XmlNamespaceManager manager) { switch (node.NodeType) { case XmlNodeType.Attribute: if (node.NamespaceUri == "http://james.newtonking.com/projects/json") { return "$" + node.LocalName; } return "@" + ResolveFullName(node, manager); case XmlNodeType.CDATA: return "#cdata-section"; case XmlNodeType.Comment: return "#comment"; case XmlNodeType.Element: if (node.NamespaceUri == "http://james.newtonking.com/projects/json") { return "$" + node.LocalName; } return ResolveFullName(node, manager); case XmlNodeType.ProcessingInstruction: return "?" + ResolveFullName(node, manager); case XmlNodeType.DocumentType: return "!" + ResolveFullName(node, manager); case XmlNodeType.XmlDeclaration: return "?xml"; case XmlNodeType.SignificantWhitespace: return "#significant-whitespace"; case XmlNodeType.Text: return "#text"; case XmlNodeType.Whitespace: return "#whitespace"; default: throw new JsonSerializationException("Unexpected XmlNodeType when getting node name: " + node.NodeType); } } private bool IsArray(IXmlNode node) { foreach (IXmlNode attribute in node.Attributes) { if (attribute.LocalName == "Array" && attribute.NamespaceUri == "http://james.newtonking.com/projects/json") { return XmlConvert.ToBoolean(attribute.Value); } } return false; } private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName) { switch (node.ChildNodes.Count) { case 1: { string propertyName = GetPropertyName(node.ChildNodes[0], manager); WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, propertyName); return; } case 0: return; } Dictionary dictionary = null; string text = null; for (int i = 0; i < node.ChildNodes.Count; i++) { IXmlNode xmlNode = node.ChildNodes[i]; string propertyName2 = GetPropertyName(xmlNode, manager); object value; if (dictionary == null) { if (text == null) { text = propertyName2; continue; } if (propertyName2 == text) { continue; } dictionary = new Dictionary(); if (i > 1) { List list = new List(i); for (int j = 0; j < i; j++) { list.Add(node.ChildNodes[j]); } dictionary.Add(text, list); } else { dictionary.Add(text, node.ChildNodes[0]); } dictionary.Add(propertyName2, xmlNode); } else if (!dictionary.TryGetValue(propertyName2, out value)) { dictionary.Add(propertyName2, xmlNode); } else { List list2 = value as List; if (list2 == null) { list2 = (List)(dictionary[propertyName2] = new List { (IXmlNode)value }); } list2.Add(xmlNode); } } if (dictionary == null) { WriteGroupedNodes(writer, manager, writePropertyName, node.ChildNodes, text); return; } foreach (KeyValuePair item in dictionary) { if (item.Value is List groupedNodes) { WriteGroupedNodes(writer, manager, writePropertyName, groupedNodes, item.Key); } else { WriteGroupedNodes(writer, manager, writePropertyName, (IXmlNode)item.Value, item.Key); } } } private void WriteGroupedNodes(JsonWriter writer, XmlNamespaceManager manager, bool writePropertyName, List groupedNodes, string elementNames) { if (groupedNodes.Count == 1 && !IsArray(groupedNodes[0])) { SerializeNode(writer, groupedNodes[0], manager, writePropertyName); return; } if (writePropertyName) { writer.WritePropertyName(elementNames); } writer.WriteStartArray(); for (int i = 0; i < groupedNodes.Count; i++) { SerializeNode(writer, groupedNodes[i], manager, writePropertyName: false); } writer.WriteEndArray(); } private void WriteGroupedNodes(JsonWriter writer, XmlNamespaceManager manager, bool writePropertyName, IXmlNode node, string elementNames) { if (!IsArray(node)) { SerializeNode(writer, node, manager, writePropertyName); return; } if (writePropertyName) { writer.WritePropertyName(elementNames); } writer.WriteStartArray(); SerializeNode(writer, node, manager, writePropertyName: false); writer.WriteEndArray(); } private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName) { switch (node.NodeType) { case XmlNodeType.Document: case XmlNodeType.DocumentFragment: SerializeGroupedNodes(writer, node, manager, writePropertyName); break; case XmlNodeType.Element: if (IsArray(node) && AllSameName(node) && node.ChildNodes.Count > 0) { SerializeGroupedNodes(writer, node, manager, writePropertyName: false); break; } manager.PushScope(); foreach (IXmlNode attribute in node.Attributes) { if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/") { string prefix = ((attribute.LocalName != "xmlns") ? XmlConvert.DecodeName(attribute.LocalName) : string.Empty); string value = attribute.Value; if (value == null) { throw new JsonSerializationException("Namespace attribute must have a value."); } manager.AddNamespace(prefix, value); } } if (writePropertyName) { writer.WritePropertyName(GetPropertyName(node, manager)); } if (!ValueAttributes(node.Attributes) && node.ChildNodes.Count == 1 && node.ChildNodes[0].NodeType == XmlNodeType.Text) { writer.WriteValue(node.ChildNodes[0].Value); } else if (node.ChildNodes.Count == 0 && node.Attributes.Count == 0) { if (((IXmlElement)node).IsEmpty) { writer.WriteNull(); } else { writer.WriteValue(string.Empty); } } else { writer.WriteStartObject(); for (int i = 0; i < node.Attributes.Count; i++) { SerializeNode(writer, node.Attributes[i], manager, writePropertyName: true); } SerializeGroupedNodes(writer, node, manager, writePropertyName: true); writer.WriteEndObject(); } manager.PopScope(); break; case XmlNodeType.Comment: if (writePropertyName) { writer.WriteComment(node.Value); } break; case XmlNodeType.Attribute: case XmlNodeType.Text: case XmlNodeType.CDATA: case XmlNodeType.ProcessingInstruction: case XmlNodeType.Whitespace: case XmlNodeType.SignificantWhitespace: if ((!(node.NamespaceUri == "http://www.w3.org/2000/xmlns/") || !(node.Value == "http://james.newtonking.com/projects/json")) && (!(node.NamespaceUri == "http://james.newtonking.com/projects/json") || !(node.LocalName == "Array"))) { if (writePropertyName) { writer.WritePropertyName(GetPropertyName(node, manager)); } writer.WriteValue(node.Value); } break; case XmlNodeType.XmlDeclaration: { IXmlDeclaration xmlDeclaration = (IXmlDeclaration)node; writer.WritePropertyName(GetPropertyName(node, manager)); writer.WriteStartObject(); if (!StringUtils.IsNullOrEmpty(xmlDeclaration.Version)) { writer.WritePropertyName("@version"); writer.WriteValue(xmlDeclaration.Version); } if (!StringUtils.IsNullOrEmpty(xmlDeclaration.Encoding)) { writer.WritePropertyName("@encoding"); writer.WriteValue(xmlDeclaration.Encoding); } if (!StringUtils.IsNullOrEmpty(xmlDeclaration.Standalone)) { writer.WritePropertyName("@standalone"); writer.WriteValue(xmlDeclaration.Standalone); } writer.WriteEndObject(); break; } case XmlNodeType.DocumentType: { IXmlDocumentType xmlDocumentType = (IXmlDocumentType)node; writer.WritePropertyName(GetPropertyName(node, manager)); writer.WriteStartObject(); if (!StringUtils.IsNullOrEmpty(xmlDocumentType.Name)) { writer.WritePropertyName("@name"); writer.WriteValue(xmlDocumentType.Name); } if (!StringUtils.IsNullOrEmpty(xmlDocumentType.Public)) { writer.WritePropertyName("@public"); writer.WriteValue(xmlDocumentType.Public); } if (!StringUtils.IsNullOrEmpty(xmlDocumentType.System)) { writer.WritePropertyName("@system"); writer.WriteValue(xmlDocumentType.System); } if (!StringUtils.IsNullOrEmpty(xmlDocumentType.InternalSubset)) { writer.WritePropertyName("@internalSubset"); writer.WriteValue(xmlDocumentType.InternalSubset); } writer.WriteEndObject(); break; } default: throw new JsonSerializationException("Unexpected XmlNodeType when serializing nodes: " + node.NodeType); } } private static bool AllSameName(IXmlNode node) { foreach (IXmlNode childNode in node.ChildNodes) { if (childNode.LocalName != node.LocalName) { return false; } } return true; } public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Expected O, but got Unknown //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown switch (reader.TokenType) { case JsonToken.Null: return null; default: throw JsonSerializationException.Create(reader, "XmlNodeConverter can only convert JSON that begins with an object."); case JsonToken.StartObject: { XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable()); IXmlDocument xmlDocument = null; IXmlNode xmlNode = null; if (typeof(XObject).IsAssignableFrom(objectType)) { if (objectType != typeof(XContainer) && objectType != typeof(XDocument) && objectType != typeof(XElement) && objectType != typeof(XNode) && objectType != typeof(XObject)) { throw JsonSerializationException.Create(reader, "XmlNodeConverter only supports deserializing XDocument, XElement, XContainer, XNode or XObject."); } xmlDocument = new XDocumentWrapper(new XDocument()); xmlNode = xmlDocument; } if (typeof(XmlNode).IsAssignableFrom(objectType)) { if (objectType != typeof(XmlDocument) && objectType != typeof(XmlElement) && objectType != typeof(XmlNode)) { throw JsonSerializationException.Create(reader, "XmlNodeConverter only supports deserializing XmlDocument, XmlElement or XmlNode."); } xmlDocument = new XmlDocumentWrapper(new XmlDocument { XmlResolver = null }); xmlNode = xmlDocument; } if (xmlDocument == null || xmlNode == null) { throw JsonSerializationException.Create(reader, "Unexpected type when converting XML: " + objectType); } if (!StringUtils.IsNullOrEmpty(DeserializeRootElementName)) { ReadElement(reader, xmlDocument, xmlNode, DeserializeRootElementName, manager); } else { reader.ReadAndAssert(); DeserializeNode(reader, xmlDocument, manager, xmlNode); } if (objectType == typeof(XElement)) { XElement val = (XElement)xmlDocument.DocumentElement.WrappedNode; ((XNode)val).Remove(); return (object?)val; } if (objectType == typeof(XmlElement)) { return xmlDocument.DocumentElement.WrappedNode; } return xmlDocument.WrappedNode; } } } private void DeserializeValue(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, string propertyName, IXmlNode currentNode) { if (!EncodeSpecialCharacters) { switch (propertyName) { case "#text": currentNode.AppendChild(document.CreateTextNode(ConvertTokenToXmlValue(reader))); return; case "#cdata-section": currentNode.AppendChild(document.CreateCDataSection(ConvertTokenToXmlValue(reader))); return; case "#whitespace": currentNode.AppendChild(document.CreateWhitespace(ConvertTokenToXmlValue(reader))); return; case "#significant-whitespace": currentNode.AppendChild(document.CreateSignificantWhitespace(ConvertTokenToXmlValue(reader))); return; } if (!StringUtils.IsNullOrEmpty(propertyName) && propertyName[0] == '?') { CreateInstruction(reader, document, currentNode, propertyName); return; } if (string.Equals(propertyName, "!DOCTYPE", StringComparison.OrdinalIgnoreCase)) { CreateDocumentType(reader, document, currentNode); return; } } if (reader.TokenType == JsonToken.StartArray) { ReadArrayElements(reader, document, propertyName, currentNode, manager); } else { ReadElement(reader, document, currentNode, propertyName, manager); } } private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager) { if (StringUtils.IsNullOrEmpty(propertyName)) { throw JsonSerializationException.Create(reader, "XmlNodeConverter cannot convert JSON with an empty property name to XML."); } Dictionary attributeNameValues = null; string elementPrefix = null; if (!EncodeSpecialCharacters) { attributeNameValues = (ShouldReadInto(reader) ? ReadAttributeElements(reader, manager) : null); elementPrefix = MiscellaneousUtils.GetPrefix(propertyName); if (StringUtils.StartsWith(propertyName, '@')) { string text = propertyName.Substring(1); string prefix = MiscellaneousUtils.GetPrefix(text); AddAttribute(reader, document, currentNode, propertyName, text, manager, prefix); return; } if (StringUtils.StartsWith(propertyName, '$')) { switch (propertyName) { case "$values": propertyName = propertyName.Substring(1); elementPrefix = manager.LookupPrefix("http://james.newtonking.com/projects/json"); CreateElement(reader, document, currentNode, propertyName, manager, elementPrefix, attributeNameValues); return; case "$id": case "$ref": case "$type": case "$value": { string attributeName = propertyName.Substring(1); string attributePrefix = manager.LookupPrefix("http://james.newtonking.com/projects/json"); AddAttribute(reader, document, currentNode, propertyName, attributeName, manager, attributePrefix); return; } } } } else if (ShouldReadInto(reader)) { reader.ReadAndAssert(); } CreateElement(reader, document, currentNode, propertyName, manager, elementPrefix, attributeNameValues); } private void CreateElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string elementName, XmlNamespaceManager manager, string? elementPrefix, Dictionary? attributeNameValues) { IXmlElement xmlElement = CreateElement(elementName, document, elementPrefix, manager); currentNode.AppendChild(xmlElement); if (attributeNameValues != null) { foreach (KeyValuePair attributeNameValue in attributeNameValues) { string text = XmlConvert.EncodeName(attributeNameValue.Key); string prefix = MiscellaneousUtils.GetPrefix(attributeNameValue.Key); IXmlNode attributeNode = ((!StringUtils.IsNullOrEmpty(prefix)) ? document.CreateAttribute(text, manager.LookupNamespace(prefix) ?? string.Empty, attributeNameValue.Value) : document.CreateAttribute(text, attributeNameValue.Value)); xmlElement.SetAttributeNode(attributeNode); } } switch (reader.TokenType) { case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Date: case JsonToken.Bytes: { string text2 = ConvertTokenToXmlValue(reader); if (text2 != null) { xmlElement.AppendChild(document.CreateTextNode(text2)); } break; } case JsonToken.EndObject: manager.RemoveNamespace(string.Empty, manager.DefaultNamespace); break; default: manager.PushScope(); DeserializeNode(reader, document, manager, xmlElement); manager.PopScope(); manager.RemoveNamespace(string.Empty, manager.DefaultNamespace); break; case JsonToken.Null: break; } } private static void AddAttribute(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, string attributeName, XmlNamespaceManager manager, string? attributePrefix) { if (currentNode.NodeType == XmlNodeType.Document) { throw JsonSerializationException.Create(reader, "JSON root object has property '{0}' that will be converted to an attribute. A root object cannot have any attribute properties. Consider specifying a DeserializeRootElementName.".FormatWith(CultureInfo.InvariantCulture, propertyName)); } string text = XmlConvert.EncodeName(attributeName); string value = ConvertTokenToXmlValue(reader); IXmlNode attributeNode = ((!StringUtils.IsNullOrEmpty(attributePrefix)) ? document.CreateAttribute(text, manager.LookupNamespace(attributePrefix), value) : document.CreateAttribute(text, value)); ((IXmlElement)currentNode).SetAttributeNode(attributeNode); } private static string? ConvertTokenToXmlValue(JsonReader reader) { switch (reader.TokenType) { case JsonToken.String: return reader.Value?.ToString(); case JsonToken.Integer: if (reader.Value is BigInteger bigInteger) { return bigInteger.ToString(CultureInfo.InvariantCulture); } return XmlConvert.ToString(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture)); case JsonToken.Float: if (reader.Value is decimal num) { return XmlConvert.ToString(num); } if (reader.Value is float num2) { return XmlConvert.ToString(num2); } return XmlConvert.ToString(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture)); case JsonToken.Boolean: return XmlConvert.ToString(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture)); case JsonToken.Date: { if (reader.Value is DateTimeOffset dateTimeOffset) { return XmlConvert.ToString(dateTimeOffset); } DateTime dateTime = Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture); return XmlConvert.ToString(dateTime, DateTimeUtils.ToSerializationMode(dateTime.Kind)); } case JsonToken.Bytes: return Convert.ToBase64String((byte[])reader.Value); case JsonToken.Null: return null; default: throw JsonSerializationException.Create(reader, "Cannot get an XML string value from token type '{0}'.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType)); } } private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager) { string prefix = MiscellaneousUtils.GetPrefix(propertyName); IXmlElement xmlElement = CreateElement(propertyName, document, prefix, manager); currentNode.AppendChild(xmlElement); int num = 0; while (reader.Read() && reader.TokenType != JsonToken.EndArray) { DeserializeValue(reader, document, manager, propertyName, xmlElement); num++; } if (WriteArrayAttribute) { AddJsonArrayAttribute(xmlElement, document); } if (num != 1 || !WriteArrayAttribute) { return; } foreach (IXmlNode childNode in xmlElement.ChildNodes) { if (childNode is IXmlElement xmlElement2 && xmlElement2.LocalName == propertyName) { AddJsonArrayAttribute(xmlElement2, document); break; } } } private void AddJsonArrayAttribute(IXmlElement element, IXmlDocument document) { element.SetAttributeNode(document.CreateAttribute("json:Array", "http://james.newtonking.com/projects/json", "true")); if (element is XElementWrapper && element.GetPrefixOfNamespace("http://james.newtonking.com/projects/json") == null) { element.SetAttributeNode(document.CreateAttribute("xmlns:json", "http://www.w3.org/2000/xmlns/", "http://james.newtonking.com/projects/json")); } } private bool ShouldReadInto(JsonReader reader) { switch (reader.TokenType) { case JsonToken.StartConstructor: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Date: case JsonToken.Bytes: return false; default: return true; } } private Dictionary? ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager) { Dictionary dictionary = null; bool flag = false; while (!flag && reader.Read()) { switch (reader.TokenType) { case JsonToken.PropertyName: { string text = reader.Value.ToString(); if (!StringUtils.IsNullOrEmpty(text)) { switch (text[0]) { case '@': { if (dictionary == null) { dictionary = new Dictionary(); } text = text.Substring(1); reader.ReadAndAssert(); string value = ConvertTokenToXmlValue(reader); dictionary.Add(text, value); if (IsNamespaceAttribute(text, out string prefix)) { manager.AddNamespace(prefix, value); } break; } case '$': switch (text) { case "$values": case "$id": case "$ref": case "$type": case "$value": { string text2 = manager.LookupPrefix("http://james.newtonking.com/projects/json"); if (text2 == null) { if (dictionary == null) { dictionary = new Dictionary(); } int? num = null; int? num2; while (true) { num2 = num; if (manager.LookupNamespace("json" + num2) == null) { break; } num = num.GetValueOrDefault() + 1; } num2 = num; text2 = "json" + num2; dictionary.Add("xmlns:" + text2, "http://james.newtonking.com/projects/json"); manager.AddNamespace(text2, "http://james.newtonking.com/projects/json"); } if (text == "$values") { flag = true; break; } text = text.Substring(1); reader.ReadAndAssert(); if (!JsonTokenUtils.IsPrimitiveToken(reader.TokenType)) { throw JsonSerializationException.Create(reader, "Unexpected JsonToken: " + reader.TokenType); } if (dictionary == null) { dictionary = new Dictionary(); } string value = reader.Value?.ToString(); dictionary.Add(text2 + ":" + text, value); break; } default: flag = true; break; } break; default: flag = true; break; } } else { flag = true; } break; } case JsonToken.Comment: case JsonToken.EndObject: flag = true; break; default: throw JsonSerializationException.Create(reader, "Unexpected JsonToken: " + reader.TokenType); } } return dictionary; } private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName) { if (propertyName == "?xml") { string text = null; string encoding = null; string standalone = null; while (reader.Read() && reader.TokenType != JsonToken.EndObject) { switch (reader.Value?.ToString()) { case "@version": reader.ReadAndAssert(); text = ConvertTokenToXmlValue(reader); break; case "@encoding": reader.ReadAndAssert(); encoding = ConvertTokenToXmlValue(reader); break; case "@standalone": reader.ReadAndAssert(); standalone = ConvertTokenToXmlValue(reader); break; default: throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value); } } if (text == null) { throw JsonSerializationException.Create(reader, "Version not specified for XML declaration."); } IXmlNode newChild = document.CreateXmlDeclaration(text, encoding, standalone); currentNode.AppendChild(newChild); } else { IXmlNode newChild2 = document.CreateProcessingInstruction(propertyName.Substring(1), ConvertTokenToXmlValue(reader)); currentNode.AppendChild(newChild2); } } private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNode currentNode) { string text = null; string publicId = null; string systemId = null; string internalSubset = null; while (reader.Read() && reader.TokenType != JsonToken.EndObject) { switch (reader.Value?.ToString()) { case "@name": reader.ReadAndAssert(); text = ConvertTokenToXmlValue(reader); break; case "@public": reader.ReadAndAssert(); publicId = ConvertTokenToXmlValue(reader); break; case "@system": reader.ReadAndAssert(); systemId = ConvertTokenToXmlValue(reader); break; case "@internalSubset": reader.ReadAndAssert(); internalSubset = ConvertTokenToXmlValue(reader); break; default: throw JsonSerializationException.Create(reader, "Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value); } } if (text == null) { throw JsonSerializationException.Create(reader, "Name not specified for XML document type."); } IXmlNode newChild = document.CreateXmlDocumentType(text, publicId, systemId, internalSubset); currentNode.AppendChild(newChild); } private IXmlElement CreateElement(string elementName, IXmlDocument document, string? elementPrefix, XmlNamespaceManager manager) { string text = (EncodeSpecialCharacters ? XmlConvert.EncodeLocalName(elementName) : XmlConvert.EncodeName(elementName)); string text2 = (StringUtils.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix)); if (StringUtils.IsNullOrEmpty(text2)) { return document.CreateElement(text); } return document.CreateElement(text, text2); } private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode) { do { switch (reader.TokenType) { case JsonToken.PropertyName: { if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null) { throw JsonSerializationException.Create(reader, "JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifying a DeserializeRootElementName."); } string text = reader.Value.ToString(); reader.ReadAndAssert(); if (reader.TokenType == JsonToken.StartArray) { int num = 0; while (reader.Read() && reader.TokenType != JsonToken.EndArray) { DeserializeValue(reader, document, manager, text, currentNode); num++; } if (num != 1 || !WriteArrayAttribute) { break; } MiscellaneousUtils.GetQualifiedNameParts(text, out string prefix, out string localName); string text2 = (StringUtils.IsNullOrEmpty(prefix) ? manager.DefaultNamespace : manager.LookupNamespace(prefix)); foreach (IXmlNode childNode in currentNode.ChildNodes) { if (childNode is IXmlElement xmlElement && xmlElement.LocalName == localName && xmlElement.NamespaceUri == text2) { AddJsonArrayAttribute(xmlElement, document); break; } } } else { DeserializeValue(reader, document, manager, text, currentNode); } break; } case JsonToken.StartConstructor: { string propertyName = reader.Value.ToString(); while (reader.Read() && reader.TokenType != JsonToken.EndConstructor) { DeserializeValue(reader, document, manager, propertyName, currentNode); } break; } case JsonToken.Comment: currentNode.AppendChild(document.CreateComment((string)reader.Value)); break; case JsonToken.EndObject: case JsonToken.EndArray: return; default: throw JsonSerializationException.Create(reader, "Unexpected JsonToken when deserializing node: " + reader.TokenType); } } while (reader.Read()); } private bool IsNamespaceAttribute(string attributeName, [NotNullWhen(true)] out string? prefix) { if (attributeName.StartsWith("xmlns", StringComparison.Ordinal)) { if (attributeName.Length == 5) { prefix = string.Empty; return true; } if (attributeName[5] == ':') { prefix = attributeName.Substring(6, attributeName.Length - 6); return true; } } prefix = null; return false; } private bool ValueAttributes(List c) { foreach (IXmlNode item in c) { if (!(item.NamespaceUri == "http://james.newtonking.com/projects/json") && (!(item.NamespaceUri == "http://www.w3.org/2000/xmlns/") || !(item.Value == "http://james.newtonking.com/projects/json"))) { return true; } } return false; } public override bool CanConvert(Type valueType) { if (valueType.AssignableToTypeName("System.Xml.Linq.XObject", searchInterfaces: false)) { return IsXObject(valueType); } if (valueType.AssignableToTypeName("System.Xml.XmlNode", searchInterfaces: false)) { return IsXmlNode(valueType); } return false; } [MethodImpl(MethodImplOptions.NoInlining)] private bool IsXObject(Type valueType) { return typeof(XObject).IsAssignableFrom(valueType); } [MethodImpl(MethodImplOptions.NoInlining)] private bool IsXmlNode(Type valueType) { return typeof(XmlNode).IsAssignableFrom(valueType); } } } namespace Newtonsoft.Json.Bson { internal enum BsonBinaryType : byte { Binary = 0, Function = 1, [Obsolete("This type has been deprecated in the BSON specification. Use Binary instead.")] BinaryOld = 2, [Obsolete("This type has been deprecated in the BSON specification. Use Uuid instead.")] UuidOld = 3, Uuid = 4, Md5 = 5, UserDefined = 128 } internal class BsonBinaryWriter { private static readonly Encoding Encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); private readonly BinaryWriter _writer; private byte[] _largeByteBuffer; public DateTimeKind DateTimeKindHandling { get; set; } public BsonBinaryWriter(BinaryWriter writer) { DateTimeKindHandling = DateTimeKind.Utc; _writer = writer; } public void Flush() { _writer.Flush(); } public void Close() { _writer.Close(); } public void WriteToken(BsonToken t) { CalculateSize(t); WriteTokenInternal(t); } private void WriteTokenInternal(BsonToken t) { switch (t.Type) { case BsonType.Object: { BsonObject bsonObject = (BsonObject)t; _writer.Write(bsonObject.CalculatedSize); foreach (BsonProperty item in bsonObject) { _writer.Write((sbyte)item.Value.Type); WriteString((string)item.Name.Value, item.Name.ByteCount, null); WriteTokenInternal(item.Value); } _writer.Write((byte)0); break; } case BsonType.Array: { BsonArray bsonArray = (BsonArray)t; _writer.Write(bsonArray.CalculatedSize); ulong num2 = 0uL; foreach (BsonToken item2 in bsonArray) { _writer.Write((sbyte)item2.Type); WriteString(num2.ToString(CultureInfo.InvariantCulture), MathUtils.IntLength(num2), null); WriteTokenInternal(item2); num2++; } _writer.Write((byte)0); break; } case BsonType.Integer: { BsonValue bsonValue3 = (BsonValue)t; _writer.Write(Convert.ToInt32(bsonValue3.Value, CultureInfo.InvariantCulture)); break; } case BsonType.Long: { BsonValue bsonValue4 = (BsonValue)t; _writer.Write(Convert.ToInt64(bsonValue4.Value, CultureInfo.InvariantCulture)); break; } case BsonType.Number: { BsonValue bsonValue2 = (BsonValue)t; _writer.Write(Convert.ToDouble(bsonValue2.Value, CultureInfo.InvariantCulture)); break; } case BsonType.String: { BsonString bsonString = (BsonString)t; WriteString((string)bsonString.Value, bsonString.ByteCount, bsonString.CalculatedSize - 4); break; } case BsonType.Boolean: _writer.Write(t == BsonBoolean.True); break; case BsonType.Date: { BsonValue bsonValue = (BsonValue)t; long num = 0L; if (bsonValue.Value is DateTime dateTime) { if (DateTimeKindHandling == DateTimeKind.Utc) { dateTime = dateTime.ToUniversalTime(); } else if (DateTimeKindHandling == DateTimeKind.Local) { dateTime = dateTime.ToLocalTime(); } num = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTime, convertToUtc: false); } else { DateTimeOffset dateTimeOffset = (DateTimeOffset)bsonValue.Value; num = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTimeOffset.UtcDateTime, dateTimeOffset.Offset); } _writer.Write(num); break; } case BsonType.Binary: { BsonBinary bsonBinary = (BsonBinary)t; byte[] array = (byte[])bsonBinary.Value; _writer.Write(array.Length); _writer.Write((byte)bsonBinary.BinaryType); _writer.Write(array); break; } case BsonType.Oid: { byte[] buffer = (byte[])((BsonValue)t).Value; _writer.Write(buffer); break; } case BsonType.Regex: { BsonRegex bsonRegex = (BsonRegex)t; WriteString((string)bsonRegex.Pattern.Value, bsonRegex.Pattern.ByteCount, null); WriteString((string)bsonRegex.Options.Value, bsonRegex.Options.ByteCount, null); break; } default: throw new ArgumentOutOfRangeException("t", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type)); case BsonType.Undefined: case BsonType.Null: break; } } private void WriteString(string s, int byteCount, int? calculatedlengthPrefix) { if (calculatedlengthPrefix.HasValue) { _writer.Write(calculatedlengthPrefix.GetValueOrDefault()); } WriteUtf8Bytes(s, byteCount); _writer.Write((byte)0); } public void WriteUtf8Bytes(string s, int byteCount) { if (s == null) { return; } if (byteCount <= 256) { if (_largeByteBuffer == null) { _largeByteBuffer = new byte[256]; } Encoding.GetBytes(s, 0, s.Length, _largeByteBuffer, 0); _writer.Write(_largeByteBuffer, 0, byteCount); } else { byte[] bytes = Encoding.GetBytes(s); _writer.Write(bytes); } } private int CalculateSize(int stringByteCount) { return stringByteCount + 1; } private int CalculateSizeWithLength(int stringByteCount, bool includeSize) { return ((!includeSize) ? 1 : 5) + stringByteCount; } private int CalculateSize(BsonToken t) { switch (t.Type) { case BsonType.Object: { BsonObject bsonObject = (BsonObject)t; int num4 = 4; foreach (BsonProperty item in bsonObject) { int num5 = 1; num5 += CalculateSize(item.Name); num5 += CalculateSize(item.Value); num4 += num5; } return bsonObject.CalculatedSize = num4 + 1; } case BsonType.Array: { BsonArray bsonArray = (BsonArray)t; int num2 = 4; ulong num3 = 0uL; foreach (BsonToken item2 in bsonArray) { num2++; num2 += CalculateSize(MathUtils.IntLength(num3)); num2 += CalculateSize(item2); num3++; } num2++; bsonArray.CalculatedSize = num2; return bsonArray.CalculatedSize; } case BsonType.Integer: return 4; case BsonType.Long: return 8; case BsonType.Number: return 8; case BsonType.String: { BsonString bsonString = (BsonString)t; string text = (string)bsonString.Value; bsonString.ByteCount = ((text != null) ? Encoding.GetByteCount(text) : 0); bsonString.CalculatedSize = CalculateSizeWithLength(bsonString.ByteCount, bsonString.IncludeLength); return bsonString.CalculatedSize; } case BsonType.Boolean: return 1; case BsonType.Undefined: case BsonType.Null: return 0; case BsonType.Date: return 8; case BsonType.Binary: { BsonBinary obj = (BsonBinary)t; byte[] array = (byte[])obj.Value; obj.CalculatedSize = 5 + array.Length; return obj.CalculatedSize; } case BsonType.Oid: return 12; case BsonType.Regex: { BsonRegex bsonRegex = (BsonRegex)t; int num = 0; num += CalculateSize(bsonRegex.Pattern); num += CalculateSize(bsonRegex.Options); bsonRegex.CalculatedSize = num; return bsonRegex.CalculatedSize; } default: throw new ArgumentOutOfRangeException("t", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type)); } } } [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] internal class BsonObjectId { public byte[] Value { get; } public BsonObjectId(byte[] value) { ValidationUtils.ArgumentNotNull(value, "value"); if (value.Length != 12) { throw new ArgumentException("An ObjectId must be 12 bytes", "value"); } Value = value; } } [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] internal class BsonReader : JsonReader { private enum BsonReaderState { Normal, ReferenceStart, ReferenceRef, ReferenceId, CodeWScopeStart, CodeWScopeCode, CodeWScopeScope, CodeWScopeScopeObject, CodeWScopeScopeEnd } private class ContainerContext { public readonly BsonType Type; public int Length; public int Position; public ContainerContext(BsonType type) { Type = type; } } private const int MaxCharBytesSize = 128; private static readonly byte[] SeqRange1 = new byte[2] { 0, 127 }; private static readonly byte[] SeqRange2 = new byte[2] { 194, 223 }; private static readonly byte[] SeqRange3 = new byte[2] { 224, 239 }; private static readonly byte[] SeqRange4 = new byte[2] { 240, 244 }; private readonly BinaryReader _reader; private readonly List _stack; private byte[] _byteBuffer; private char[] _charBuffer; private BsonType _currentElementType; private BsonReaderState _bsonReaderState; private ContainerContext _currentContext; private bool _readRootValueAsArray; private bool _jsonNet35BinaryCompatibility; private DateTimeKind _dateTimeKindHandling; [Obsolete("JsonNet35BinaryCompatibility will be removed in a future version of Json.NET.")] public bool JsonNet35BinaryCompatibility { get { return _jsonNet35BinaryCompatibility; } set { _jsonNet35BinaryCompatibility = value; } } public bool ReadRootValueAsArray { get { return _readRootValueAsArray; } set { _readRootValueAsArray = value; } } public DateTimeKind DateTimeKindHandling { get { return _dateTimeKindHandling; } set { _dateTimeKindHandling = value; } } public BsonReader(Stream stream) : this(stream, readRootValueAsArray: false, DateTimeKind.Local) { } public BsonReader(BinaryReader reader) : this(reader, readRootValueAsArray: false, DateTimeKind.Local) { } public BsonReader(Stream stream, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling) { ValidationUtils.ArgumentNotNull(stream, "stream"); _reader = new BinaryReader(stream); _stack = new List(); _readRootValueAsArray = readRootValueAsArray; _dateTimeKindHandling = dateTimeKindHandling; } public BsonReader(BinaryReader reader, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling) { ValidationUtils.ArgumentNotNull(reader, "reader"); _reader = reader; _stack = new List(); _readRootValueAsArray = readRootValueAsArray; _dateTimeKindHandling = dateTimeKindHandling; } private string ReadElement() { _currentElementType = ReadType(); return ReadString(); } public override bool Read() { try { bool flag; switch (_bsonReaderState) { case BsonReaderState.Normal: flag = ReadNormal(); break; case BsonReaderState.ReferenceStart: case BsonReaderState.ReferenceRef: case BsonReaderState.ReferenceId: flag = ReadReference(); break; case BsonReaderState.CodeWScopeStart: case BsonReaderState.CodeWScopeCode: case BsonReaderState.CodeWScopeScope: case BsonReaderState.CodeWScopeScopeObject: case BsonReaderState.CodeWScopeScopeEnd: flag = ReadCodeWScope(); break; default: throw JsonReaderException.Create(this, "Unexpected state: {0}".FormatWith(CultureInfo.InvariantCulture, _bsonReaderState)); } if (!flag) { SetToken(JsonToken.None); return false; } return true; } catch (EndOfStreamException) { SetToken(JsonToken.None); return false; } } public override void Close() { base.Close(); if (base.CloseInput) { _reader?.Close(); } } private bool ReadCodeWScope() { switch (_bsonReaderState) { case BsonReaderState.CodeWScopeStart: SetToken(JsonToken.PropertyName, "$code"); _bsonReaderState = BsonReaderState.CodeWScopeCode; return true; case BsonReaderState.CodeWScopeCode: ReadInt32(); SetToken(JsonToken.String, ReadLengthString()); _bsonReaderState = BsonReaderState.CodeWScopeScope; return true; case BsonReaderState.CodeWScopeScope: { if (base.CurrentState == State.PostValue) { SetToken(JsonToken.PropertyName, "$scope"); return true; } SetToken(JsonToken.StartObject); _bsonReaderState = BsonReaderState.CodeWScopeScopeObject; ContainerContext containerContext = new ContainerContext(BsonType.Object); PushContext(containerContext); containerContext.Length = ReadInt32(); return true; } case BsonReaderState.CodeWScopeScopeObject: { bool num = ReadNormal(); if (num && TokenType == JsonToken.EndObject) { _bsonReaderState = BsonReaderState.CodeWScopeScopeEnd; } return num; } case BsonReaderState.CodeWScopeScopeEnd: SetToken(JsonToken.EndObject); _bsonReaderState = BsonReaderState.Normal; return true; default: throw new ArgumentOutOfRangeException(); } } private bool ReadReference() { switch (base.CurrentState) { case State.ObjectStart: SetToken(JsonToken.PropertyName, "$ref"); _bsonReaderState = BsonReaderState.ReferenceRef; return true; case State.Property: if (_bsonReaderState == BsonReaderState.ReferenceRef) { SetToken(JsonToken.String, ReadLengthString()); return true; } if (_bsonReaderState == BsonReaderState.ReferenceId) { SetToken(JsonToken.Bytes, ReadBytes(12)); return true; } throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState); case State.PostValue: if (_bsonReaderState == BsonReaderState.ReferenceRef) { SetToken(JsonToken.PropertyName, "$id"); _bsonReaderState = BsonReaderState.ReferenceId; return true; } if (_bsonReaderState == BsonReaderState.ReferenceId) { SetToken(JsonToken.EndObject); _bsonReaderState = BsonReaderState.Normal; return true; } throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState); default: throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + base.CurrentState); } } private bool ReadNormal() { switch (base.CurrentState) { case State.Start: { JsonToken token2 = ((!_readRootValueAsArray) ? JsonToken.StartObject : JsonToken.StartArray); int type = ((!_readRootValueAsArray) ? 3 : 4); SetToken(token2); ContainerContext containerContext = new ContainerContext((BsonType)type); PushContext(containerContext); containerContext.Length = ReadInt32(); return true; } case State.Complete: case State.Closed: return false; case State.Property: ReadType(_currentElementType); return true; case State.ObjectStart: case State.ArrayStart: case State.PostValue: { ContainerContext currentContext = _currentContext; if (currentContext == null) { if (!base.SupportMultipleContent) { return false; } goto case State.Start; } int num = currentContext.Length - 1; if (currentContext.Position < num) { if (currentContext.Type == BsonType.Array) { ReadElement(); ReadType(_currentElementType); return true; } SetToken(JsonToken.PropertyName, ReadElement()); return true; } if (currentContext.Position == num) { if (ReadByte() != 0) { throw JsonReaderException.Create(this, "Unexpected end of object byte value."); } PopContext(); if (_currentContext != null) { MovePosition(currentContext.Length); } JsonToken token = ((currentContext.Type == BsonType.Object) ? JsonToken.EndObject : JsonToken.EndArray); SetToken(token); return true; } throw JsonReaderException.Create(this, "Read past end of current container context."); } default: throw new ArgumentOutOfRangeException(); case State.ConstructorStart: case State.Constructor: case State.Error: case State.Finished: return false; } } private void PopContext() { _stack.RemoveAt(_stack.Count - 1); if (_stack.Count == 0) { _currentContext = null; } else { _currentContext = _stack[_stack.Count - 1]; } } private void PushContext(ContainerContext newContext) { _stack.Add(newContext); _currentContext = newContext; } private byte ReadByte() { MovePosition(1); return _reader.ReadByte(); } private void ReadType(BsonType type) { switch (type) { case BsonType.Number: { double num = ReadDouble(); if (_floatParseHandling == FloatParseHandling.Decimal) { SetToken(JsonToken.Float, Convert.ToDecimal(num, CultureInfo.InvariantCulture)); } else { SetToken(JsonToken.Float, num); } break; } case BsonType.String: case BsonType.Symbol: SetToken(JsonToken.String, ReadLengthString()); break; case BsonType.Object: { SetToken(JsonToken.StartObject); ContainerContext containerContext2 = new ContainerContext(BsonType.Object); PushContext(containerContext2); containerContext2.Length = ReadInt32(); break; } case BsonType.Array: { SetToken(JsonToken.StartArray); ContainerContext containerContext = new ContainerContext(BsonType.Array); PushContext(containerContext); containerContext.Length = ReadInt32(); break; } case BsonType.Binary: { BsonBinaryType binaryType; byte[] array = ReadBinary(out binaryType); object value3 = ((binaryType != BsonBinaryType.Uuid) ? array : ((object)new Guid(array))); SetToken(JsonToken.Bytes, value3); break; } case BsonType.Undefined: SetToken(JsonToken.Undefined); break; case BsonType.Oid: { byte[] value2 = ReadBytes(12); SetToken(JsonToken.Bytes, value2); break; } case BsonType.Boolean: { bool flag = Convert.ToBoolean(ReadByte()); SetToken(JsonToken.Boolean, flag); break; } case BsonType.Date: { DateTime dateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ReadInt64()); SetToken(JsonToken.Date, DateTimeKindHandling switch { DateTimeKind.Unspecified => DateTime.SpecifyKind(dateTime, DateTimeKind.Unspecified), DateTimeKind.Local => dateTime.ToLocalTime(), _ => dateTime, }); break; } case BsonType.Null: SetToken(JsonToken.Null); break; case BsonType.Regex: { string text = ReadString(); string text2 = ReadString(); string value = "/" + text + "/" + text2; SetToken(JsonToken.String, value); break; } case BsonType.Reference: SetToken(JsonToken.StartObject); _bsonReaderState = BsonReaderState.ReferenceStart; break; case BsonType.Code: SetToken(JsonToken.String, ReadLengthString()); break; case BsonType.CodeWScope: SetToken(JsonToken.StartObject); _bsonReaderState = BsonReaderState.CodeWScopeStart; break; case BsonType.Integer: SetToken(JsonToken.Integer, (long)ReadInt32()); break; case BsonType.TimeStamp: case BsonType.Long: SetToken(JsonToken.Integer, ReadInt64()); break; default: throw new ArgumentOutOfRangeException("type", "Unexpected BsonType value: " + type); } } private byte[] ReadBinary(out BsonBinaryType binaryType) { int count = ReadInt32(); binaryType = (BsonBinaryType)ReadByte(); if (binaryType == BsonBinaryType.BinaryOld && !_jsonNet35BinaryCompatibility) { count = ReadInt32(); } return ReadBytes(count); } private string ReadString() { EnsureBuffers(); StringBuilder stringBuilder = null; int num = 0; int num2 = 0; while (true) { int num3 = num2; byte b; while (num3 < 128 && (b = _reader.ReadByte()) > 0) { _byteBuffer[num3++] = b; } int num4 = num3 - num2; num += num4; if (num3 < 128 && stringBuilder == null) { int chars = Encoding.UTF8.GetChars(_byteBuffer, 0, num4, _charBuffer, 0); MovePosition(num + 1); return new string(_charBuffer, 0, chars); } int lastFullCharStop = GetLastFullCharStop(num3 - 1); int chars2 = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0); if (stringBuilder == null) { stringBuilder = new StringBuilder(256); } stringBuilder.Append(_charBuffer, 0, chars2); if (lastFullCharStop < num4 - 1) { num2 = num4 - lastFullCharStop - 1; Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, num2); continue; } if (num3 < 128) { break; } num2 = 0; } MovePosition(num + 1); return stringBuilder.ToString(); } private string ReadLengthString() { int num = ReadInt32(); MovePosition(num); string @string = GetString(num - 1); _reader.ReadByte(); return @string; } private string GetString(int length) { if (length == 0) { return string.Empty; } EnsureBuffers(); StringBuilder stringBuilder = null; int num = 0; int num2 = 0; do { int count = ((length - num > 128 - num2) ? (128 - num2) : (length - num)); int num3 = _reader.Read(_byteBuffer, num2, count); if (num3 == 0) { throw new EndOfStreamException("Unable to read beyond the end of the stream."); } num += num3; num3 += num2; if (num3 == length) { int chars = Encoding.UTF8.GetChars(_byteBuffer, 0, num3, _charBuffer, 0); return new string(_charBuffer, 0, chars); } int lastFullCharStop = GetLastFullCharStop(num3 - 1); if (stringBuilder == null) { stringBuilder = new StringBuilder(length); } int chars2 = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0); stringBuilder.Append(_charBuffer, 0, chars2); if (lastFullCharStop < num3 - 1) { num2 = num3 - lastFullCharStop - 1; Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, num2); } else { num2 = 0; } } while (num < length); return stringBuilder.ToString(); } private int GetLastFullCharStop(int start) { int num = start; int num2 = 0; for (; num >= 0; num--) { num2 = BytesInSequence(_byteBuffer[num]); switch (num2) { case 0: continue; default: num--; break; case 1: break; } break; } if (num2 == start - num) { return start; } return num; } private int BytesInSequence(byte b) { if (b <= SeqRange1[1]) { return 1; } if (b >= SeqRange2[0] && b <= SeqRange2[1]) { return 2; } if (b >= SeqRange3[0] && b <= SeqRange3[1]) { return 3; } if (b >= SeqRange4[0] && b <= SeqRange4[1]) { return 4; } return 0; } private void EnsureBuffers() { if (_byteBuffer == null) { _byteBuffer = new byte[128]; } if (_charBuffer == null) { int maxCharCount = Encoding.UTF8.GetMaxCharCount(128); _charBuffer = new char[maxCharCount]; } } private double ReadDouble() { MovePosition(8); return _reader.ReadDouble(); } private int ReadInt32() { MovePosition(4); return _reader.ReadInt32(); } private long ReadInt64() { MovePosition(8); return _reader.ReadInt64(); } private BsonType ReadType() { MovePosition(1); return (BsonType)_reader.ReadSByte(); } private void MovePosition(int count) { _currentContext.Position += count; } private byte[] ReadBytes(int count) { MovePosition(count); return _reader.ReadBytes(count); } } internal abstract class BsonToken { public abstract BsonType Type { get; } public BsonToken Parent { get; set; } public int CalculatedSize { get; set; } } internal class BsonObject : BsonToken, IEnumerable, IEnumerable { private readonly List _children = new List(); public override BsonType Type => BsonType.Object; public void Add(string name, BsonToken token) { _children.Add(new BsonProperty { Name = new BsonString(name, includeLength: false), Value = token }); token.Parent = this; } public IEnumerator GetEnumerator() { return _children.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal class BsonArray : BsonToken, IEnumerable, IEnumerable { private readonly List _children = new List(); public override BsonType Type => BsonType.Array; public void Add(BsonToken token) { _children.Add(token); token.Parent = this; } public IEnumerator GetEnumerator() { return _children.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } internal class BsonEmpty : BsonToken { public static readonly BsonToken Null = new BsonEmpty(BsonType.Null); public static readonly BsonToken Undefined = new BsonEmpty(BsonType.Undefined); public override BsonType Type { get; } private BsonEmpty(BsonType type) { Type = type; } } internal class BsonValue : BsonToken { private readonly object _value; private readonly BsonType _type; public object Value => _value; public override BsonType Type => _type; public BsonValue(object value, BsonType type) { _value = value; _type = type; } } internal class BsonBoolean : BsonValue { public static readonly BsonBoolean False = new BsonBoolean(value: false); public static readonly BsonBoolean True = new BsonBoolean(value: true); private BsonBoolean(bool value) : base(value, BsonType.Boolean) { } } internal class BsonString : BsonValue { public int ByteCount { get; set; } public bool IncludeLength { get; } public BsonString(object value, bool includeLength) : base(value, BsonType.String) { IncludeLength = includeLength; } } internal class BsonBinary : BsonValue { public BsonBinaryType BinaryType { get; set; } public BsonBinary(byte[] value, BsonBinaryType binaryType) : base(value, BsonType.Binary) { BinaryType = binaryType; } } internal class BsonRegex : BsonToken { public BsonString Pattern { get; set; } public BsonString Options { get; set; } public override BsonType Type => BsonType.Regex; public BsonRegex(string pattern, string options) { Pattern = new BsonString(pattern, includeLength: false); Options = new BsonString(options, includeLength: false); } } internal class BsonProperty { public BsonString Name { get; set; } public BsonToken Value { get; set; } } internal enum BsonType : sbyte { Number = 1, String = 2, Object = 3, Array = 4, Binary = 5, Undefined = 6, Oid = 7, Boolean = 8, Date = 9, Null = 10, Regex = 11, Reference = 12, Code = 13, Symbol = 14, CodeWScope = 15, Integer = 16, TimeStamp = 17, Long = 18, MinKey = -1, MaxKey = sbyte.MaxValue } [Obsolete("BSON reading and writing has been moved to its own package. See https://www.nuget.org/packages/Newtonsoft.Json.Bson for more details.")] internal class BsonWriter : JsonWriter { private readonly BsonBinaryWriter _writer; private BsonToken _root; private BsonToken _parent; private string _propertyName; public DateTimeKind DateTimeKindHandling { get { return _writer.DateTimeKindHandling; } set { _writer.DateTimeKindHandling = value; } } public BsonWriter(Stream stream) { ValidationUtils.ArgumentNotNull(stream, "stream"); _writer = new BsonBinaryWriter(new BinaryWriter(stream)); } public BsonWriter(BinaryWriter writer) { ValidationUtils.ArgumentNotNull(writer, "writer"); _writer = new BsonBinaryWriter(writer); } public override void Flush() { _writer.Flush(); } protected override void WriteEnd(JsonToken token) { base.WriteEnd(token); RemoveParent(); if (base.Top == 0) { _writer.WriteToken(_root); } } public override void WriteComment(string text) { throw JsonWriterException.Create(this, "Cannot write JSON comment as BSON.", null); } public override void WriteStartConstructor(string name) { throw JsonWriterException.Create(this, "Cannot write JSON constructor as BSON.", null); } public override void WriteRaw(string json) { throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null); } public override void WriteRawValue(string json) { throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null); } public override void WriteStartArray() { base.WriteStartArray(); AddParent(new BsonArray()); } public override void WriteStartObject() { base.WriteStartObject(); AddParent(new BsonObject()); } public override void WritePropertyName(string name) { base.WritePropertyName(name); _propertyName = name; } public override void Close() { base.Close(); if (base.CloseOutput) { _writer?.Close(); } } private void AddParent(BsonToken container) { AddToken(container); _parent = container; } private void RemoveParent() { _parent = _parent.Parent; } private void AddValue(object value, BsonType type) { AddToken(new BsonValue(value, type)); } internal void AddToken(BsonToken token) { if (_parent != null) { if (_parent is BsonObject bsonObject) { bsonObject.Add(_propertyName, token); _propertyName = null; } else { ((BsonArray)_parent).Add(token); } return; } if (token.Type != BsonType.Object && token.Type != BsonType.Array) { throw JsonWriterException.Create(this, "Error writing {0} value. BSON must start with an Object or Array.".FormatWith(CultureInfo.InvariantCulture, token.Type), null); } _parent = token; _root = token; } public override void WriteValue(object value) { if (value is BigInteger bigInteger) { SetWriteState(JsonToken.Integer, null); AddToken(new BsonBinary(bigInteger.ToByteArray(), BsonBinaryType.Binary)); } else { base.WriteValue(value); } } public override void WriteNull() { base.WriteNull(); AddToken(BsonEmpty.Null); } public override void WriteUndefined() { base.WriteUndefined(); AddToken(BsonEmpty.Undefined); } public override void WriteValue(string value) { base.WriteValue(value); AddToken((value == null) ? BsonEmpty.Null : new BsonString(value, includeLength: true)); } public override void WriteValue(int value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } [CLSCompliant(false)] public override void WriteValue(uint value) { if (value > int.MaxValue) { throw JsonWriterException.Create(this, "Value is too large to fit in a signed 32 bit integer. BSON does not support unsigned values.", null); } base.WriteValue(value); AddValue(value, BsonType.Integer); } public override void WriteValue(long value) { base.WriteValue(value); AddValue(value, BsonType.Long); } [CLSCompliant(false)] public override void WriteValue(ulong value) { if (value > long.MaxValue) { throw JsonWriterException.Create(this, "Value is too large to fit in a signed 64 bit integer. BSON does not support unsigned values.", null); } base.WriteValue(value); AddValue(value, BsonType.Long); } public override void WriteValue(float value) { base.WriteValue(value); AddValue(value, BsonType.Number); } public override void WriteValue(double value) { base.WriteValue(value); AddValue(value, BsonType.Number); } public override void WriteValue(bool value) { base.WriteValue(value); AddToken(value ? BsonBoolean.True : BsonBoolean.False); } public override void WriteValue(short value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } [CLSCompliant(false)] public override void WriteValue(ushort value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } public override void WriteValue(char value) { base.WriteValue(value); string text = null; text = value.ToString(CultureInfo.InvariantCulture); AddToken(new BsonString(text, includeLength: true)); } public override void WriteValue(byte value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } [CLSCompliant(false)] public override void WriteValue(sbyte value) { base.WriteValue(value); AddValue(value, BsonType.Integer); } public override void WriteValue(decimal value) { base.WriteValue(value); AddValue(value, BsonType.Number); } public override void WriteValue(DateTime value) { base.WriteValue(value); value = DateTimeUtils.EnsureDateTime(value, base.DateTimeZoneHandling); AddValue(value, BsonType.Date); } public override void WriteValue(DateTimeOffset value) { base.WriteValue(value); AddValue(value, BsonType.Date); } public override void WriteValue(byte[] value) { if (value == null) { WriteNull(); return; } base.WriteValue(value); AddToken(new BsonBinary(value, BsonBinaryType.Binary)); } public override void WriteValue(Guid value) { base.WriteValue(value); AddToken(new BsonBinary(value.ToByteArray(), BsonBinaryType.Uuid)); } public override void WriteValue(TimeSpan value) { base.WriteValue(value); AddToken(new BsonString(value.ToString(), includeLength: true)); } public override void WriteValue(Uri value) { if (value == null) { WriteNull(); return; } base.WriteValue(value); AddToken(new BsonString(value.ToString(), includeLength: true)); } public void WriteObjectId(byte[] value) { ValidationUtils.ArgumentNotNull(value, "value"); if (value.Length != 12) { throw JsonWriterException.Create(this, "An object id must be 12 bytes", null); } SetWriteState(JsonToken.Undefined, null); AddValue(value, BsonType.Oid); } public void WriteRegex(string pattern, string options) { ValidationUtils.ArgumentNotNull(pattern, "pattern"); SetWriteState(JsonToken.Undefined, null); AddToken(new BsonRegex(pattern, options)); } } }