197 lines
7.3 KiB
C#
197 lines
7.3 KiB
C#
using System.Text.Encodings.Web;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using SPTarkov.Server.Core.Models;
|
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
|
using SPTarkov.Server.Core.Models.Eft.Ws;
|
|
using SPTarkov.Server.Core.Models.Enums;
|
|
using SPTarkov.Server.Core.Models.Spt.Dialog;
|
|
using SPTarkov.Server.Core.Utils.Json.Converters;
|
|
using SPTarkov.Common.Annotations;
|
|
|
|
namespace SPTarkov.Server.Core.Utils;
|
|
|
|
[Injectable(InjectionType.Singleton)]
|
|
public class JsonUtil
|
|
{
|
|
private static JsonSerializerOptions jsonSerializerOptionsNoIndent = new()
|
|
{
|
|
WriteIndented = false,
|
|
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
|
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
|
|
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
|
Converters =
|
|
{
|
|
new ListOrTConverterFactory(),
|
|
new DictionaryOrListConverter(),
|
|
new EftEnumConverter<SptAirdropTypeEnum>(),
|
|
new EftEnumConverter<GiftSenderType>(),
|
|
new EftEnumConverter<SeasonalEventType>(),
|
|
new EftEnumConverter<ProfileChangeEventType>(),
|
|
new EftEnumConverter<QuestStatusEnum>(),
|
|
new EftEnumConverter<RewardType>(),
|
|
new EftEnumConverter<SideType>(),
|
|
new EftEnumConverter<BonusSkillType>(),
|
|
new EftEnumConverter<NotificationEventType>(),
|
|
new EftEnumConverter<QuestTypeEnum>(),
|
|
new EftEnumConverter<RewardType>(),
|
|
new EftEnumConverter<ExitStatus>(),
|
|
new EftEnumConverter<MemberCategory>(),
|
|
new EftEnumConverter<PinLockState>(),
|
|
new EftEnumConverter<PlayerSideMask>(),
|
|
new EftEnumConverter<DamageEffectType>(),
|
|
new EftEnumConverter<RepairStrategyType>(),
|
|
new EftEnumConverter<ThrowWeapType>(),
|
|
new EftEnumConverter<EventType>(),
|
|
new EftEnumConverter<TraderServiceType>(),
|
|
new EftEnumConverter<CurrencyType>(),
|
|
new EftEnumConverter<RadioStationType>(),
|
|
new EftEnumConverter<ArmorMaterial>(),
|
|
new EftEnumConverter<RequirementState>(),
|
|
new EftEnumConverter<ExfiltrationType>(),
|
|
new EftEnumConverter<EquipmentSlots>(),
|
|
new EftListEnumConverter<EquipmentSlots>(),
|
|
new BaseInteractionRequestDataConverter()
|
|
}
|
|
};
|
|
|
|
private static JsonSerializerOptions jsonSerializerOptionsIndented = new(jsonSerializerOptionsNoIndent)
|
|
{
|
|
WriteIndented = true
|
|
};
|
|
|
|
|
|
/// <summary>
|
|
/// Convert JSON into an object
|
|
/// </summary>
|
|
/// <typeparam name="T">The type of the object to deserialize to</typeparam>
|
|
/// <param name="json">The JSON string to deserialize</param>
|
|
/// <returns>Deserialized object or null</returns>
|
|
public T? Deserialize<T>(string? json)
|
|
{
|
|
return string.IsNullOrEmpty(json) ? default : JsonSerializer.Deserialize<T>(json, jsonSerializerOptionsNoIndent);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert JSON into an object
|
|
/// </summary>
|
|
/// <param name="json">The JSON string to deserialize</param>
|
|
/// <param name="type">The type of the object to deserialize to</param>
|
|
/// <returns></returns>
|
|
public object? Deserialize(string? json, Type type)
|
|
{
|
|
return string.IsNullOrEmpty(json) ? null : JsonSerializer.Deserialize(json, type, jsonSerializerOptionsNoIndent);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert JSON into an object from a file
|
|
/// </summary>
|
|
/// <param name="file">The JSON File to read</param>
|
|
/// <returns>T</returns>
|
|
public T? DeserializeFromFile<T>(string file)
|
|
{
|
|
if (!File.Exists(file))
|
|
{
|
|
return default;
|
|
}
|
|
|
|
using (FileStream fs = new(file, FileMode.Open, FileAccess.Read))
|
|
{
|
|
return JsonSerializer.Deserialize<T>(fs, jsonSerializerOptionsNoIndent);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert JSON into an object from a file
|
|
/// </summary>
|
|
/// <param name="file">The JSON File to read</param>
|
|
/// <param name="type">The type of the object to deserialize to</param>
|
|
/// <returns>object</returns>
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert JSON into an object from a FileStream
|
|
/// </summary>
|
|
/// <param name="fs">The file stream to deserialize</param>
|
|
/// <param name="type">The type of the object to deserialize to</param>
|
|
/// <returns></returns>
|
|
public object? DeserializeFromFileStream(FileStream fs, Type type)
|
|
{
|
|
return JsonSerializer.Deserialize(fs, type, jsonSerializerOptionsNoIndent);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert an object into JSON
|
|
/// </summary>
|
|
/// <typeparam name="T">Type of the object being serialised</typeparam>
|
|
/// <param name="obj">Object to serialise</param>
|
|
/// <param name="indented">Should JSON be indented</param>
|
|
/// <returns>Serialised object as JSON, or null</returns>
|
|
public string? Serialize<T>(T? obj, bool indented = false)
|
|
{
|
|
return obj == null ? null : JsonSerializer.Serialize(obj, indented ? jsonSerializerOptionsIndented : jsonSerializerOptionsNoIndent);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert an object into JSON
|
|
/// </summary>
|
|
/// <param name="obj">Object to serialise</param>
|
|
/// <param name="type">Type of object being serialsied</param>
|
|
/// <param name="indented">Should JSON be indented</param>
|
|
/// <returns></returns>
|
|
public string? Serialize(object? obj, Type type, bool indented = false)
|
|
{
|
|
return obj == null ? null : JsonSerializer.Serialize(obj, type, indented ? jsonSerializerOptionsIndented : jsonSerializerOptionsNoIndent);
|
|
}
|
|
|
|
private void AddConverter(JsonSerializerOptions options, JsonConverter newConverter)
|
|
{
|
|
if (!options.Converters.Any(c => c.GetType() == newConverter.GetType()))
|
|
{
|
|
options.Converters.Add(newConverter);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Register a Json converter to serializer options
|
|
/// </summary>
|
|
/// <param name="converter">The converter to add</param>
|
|
public void RegisterJsonConverter(JsonConverter converter)
|
|
{
|
|
// This might actually be a terrible thing to do, but it is what it is for now
|
|
|
|
if (!jsonSerializerOptionsNoIndent.IsReadOnly)
|
|
{
|
|
AddConverter(jsonSerializerOptionsNoIndent, converter);
|
|
}
|
|
else
|
|
{
|
|
var noIndentConverter = new JsonSerializerOptions(jsonSerializerOptionsNoIndent);
|
|
AddConverter(noIndentConverter, converter);
|
|
jsonSerializerOptionsNoIndent = noIndentConverter;
|
|
}
|
|
|
|
if (!jsonSerializerOptionsIndented.IsReadOnly)
|
|
{
|
|
AddConverter(jsonSerializerOptionsIndented, converter);
|
|
}
|
|
else
|
|
{
|
|
var indentedConverter = new JsonSerializerOptions(jsonSerializerOptionsIndented);
|
|
AddConverter(indentedConverter, converter);
|
|
jsonSerializerOptionsIndented = indentedConverter;
|
|
}
|
|
}
|
|
}
|