using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization; using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Utils.Json; namespace SPTarkov.Server.Core.Utils; [Injectable(InjectionType.Singleton)] public class JsonUtil { public static JsonSerializerOptions? JsonSerializerOptionsIndented { get; private set; } public static JsonSerializerOptions? JsonSerializerOptionsNoIndent { get; private set; } public JsonUtil(IEnumerable registrators) { JsonSerializerOptionsNoIndent = new JsonSerializerOptions() { // This is required for JSONC support ReadCommentHandling = JsonCommentHandling.Skip, WriteIndented = false, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, }; foreach (var registrator in registrators) { foreach (var converter in registrator.GetJsonConverters()) { JsonSerializerOptionsNoIndent.Converters.Add(converter); } } JsonSerializerOptionsIndented = new JsonSerializerOptions(JsonSerializerOptionsNoIndent) { WriteIndented = true }; } /// /// Convert JSON into an object /// /// The type of the object to deserialize to /// The JSON string to deserialize /// Deserialized object or null public T? Deserialize(string? json) { return string.IsNullOrEmpty(json) ? default : JsonSerializer.Deserialize(json, JsonSerializerOptionsNoIndent); } /// /// Convert JSON into an object /// /// The JSON string to deserialize /// The type of the object to deserialize to /// public object? Deserialize(string? json, Type type) { return string.IsNullOrEmpty(json) ? null : JsonSerializer.Deserialize(json, type, JsonSerializerOptionsNoIndent); } /// /// Convert JSON into an object from a file /// /// The JSON File to read /// T public T? DeserializeFromFile(string file) { if (!File.Exists(file)) { return default; } using (FileStream fs = new(file, FileMode.Open, FileAccess.Read)) { return JsonSerializer.Deserialize(fs, JsonSerializerOptionsNoIndent); } } /// /// Convert JSON into an object from a file asynchronously /// /// The JSON File to read /// T public async Task DeserializeFromFileAsync(string file) { if (!File.Exists(file)) { return default; } await using FileStream fs = new(file, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true); return await JsonSerializer.DeserializeAsync(fs, JsonSerializerOptionsNoIndent); } /// /// Convert JSON into an object from a file /// /// The JSON File to read /// The type of the object to deserialize to /// object public object? DeserializeFromFile(string file, Type type) { if (!File.Exists(file)) { return default; } using (FileStream fs = new(file, FileMode.Open, FileAccess.Read)) { return JsonSerializer.Deserialize(fs, type, JsonSerializerOptionsNoIndent); } } /// /// Convert JSON into an object from a file asynchronously /// /// The JSON File to read /// The type of the object to deserialize to /// object public async Task DeserializeFromFileAsync(string file, Type type) { if (!File.Exists(file)) { return default; } await using FileStream fs = new(file, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true); return await JsonSerializer.DeserializeAsync(fs, type, JsonSerializerOptionsNoIndent); } /// /// Convert JSON into an object from a FileStream /// /// The file stream to deserialize /// The type of the object to deserialize to /// public object? DeserializeFromFileStream(FileStream fs, Type type) { return JsonSerializer.Deserialize(fs, type, JsonSerializerOptionsNoIndent); } /// /// Convert JSON into an object from a FileStream asynchronously /// /// The file stream to deserialize /// The type of the object to deserialize to /// public async Task DeserializeFromFileStreamAsync(FileStream fs, Type type) { return await JsonSerializer.DeserializeAsync(fs, type, JsonSerializerOptionsNoIndent); } /// /// Convert JSON into an object from a MemoryStream asynchronously /// /// The memory stream to deserialize /// T public async Task DeserializeFromMemoryStreamAsync(MemoryStream ms) { return await JsonSerializer.DeserializeAsync(ms, JsonSerializerOptionsNoIndent); } /// /// Convert an object into JSON /// /// Type of the object being serialised /// Object to serialise /// Should JSON be indented /// Serialised object as JSON, or null public string? Serialize(T? obj, bool indented = false) { return obj == null ? null : JsonSerializer.Serialize(obj, indented ? JsonSerializerOptionsIndented : JsonSerializerOptionsNoIndent); } /// /// Convert an object into JSON /// /// Object to serialise /// Type of object being serialized /// Should JSON be indented /// Serialized text public string? Serialize(object? obj, Type type, bool indented = false) { return obj == null ? null : JsonSerializer.Serialize(obj, type, indented ? JsonSerializerOptionsIndented : JsonSerializerOptionsNoIndent); } }