Json util refactor

This commit is contained in:
Cj
2025-05-30 09:10:52 -04:00
parent a12deb3839
commit f30dda24e3
42 changed files with 195 additions and 113 deletions
@@ -616,6 +616,7 @@ public record Ban
}
}
[EftEnumConverter]
public enum BanType
{
Chat,
@@ -408,6 +408,7 @@ public record LockableComponent
public LockableKeyComponent? KeyComponent { get; set; }
}
[EftEnumConverter]
public enum PinLockState
{
Free,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Eft.Ws;
[EftEnumConverter]
public enum NotificationEventType
{
AssortmentUnlockRule,
@@ -1,3 +1,5 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
public enum AirdropTypeEnum
@@ -8,6 +10,7 @@ public enum AirdropTypeEnum
Weapon
}
[EftEnumConverter]
public enum SptAirdropTypeEnum
{
mixed,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum ArmorMaterial
{
UHMWPE,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum BodyPartColliderType
{
None = -1,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum BonusSkillType
{
Physical,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum BuffType
{
WeaponSpread,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum CurrencyType
{
RUB,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum DamageEffectType
{
HeavyBleeding,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftListEnumConverter]
public enum DamageType
{
Undefined = 1,
@@ -1,5 +1,9 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
[EftListEnumConverter]
public enum EquipmentSlots
{
Headwear,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum EventType
{
None,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum ExfiltrationType
{
Individual,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum ExitStatus
{
SURVIVED,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum GiftSenderType
{
System,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum MemberCategory
{
Default = 0,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftListEnumConverter]
public enum PlayerSide
{
Usec = 1,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum PlayerSideMask
{
None,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum QuestStatusEnum
{
Locked = 0,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum QuestTypeEnum
{
PickUp,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum RepairStrategyType
{
MeleeWeapon,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum RequirementState
{
None,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum RewardType
{
Experience,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum SeasonalEventType
{
None,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum SideType
{
Pmc,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum ThrowWeapType
{
frag_grenade,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Enums;
[EftEnumConverter]
public enum TraderServiceType
{
ExUsecLoyalty,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Logging;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Logging;
[EftEnumConverter]
public enum LogBackgroundColor
{
Black = 40,
@@ -1,5 +1,8 @@
namespace SPTarkov.Server.Core.Models.Logging;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Logging;
[EftEnumConverter]
public enum LogTextColor
{
Black = 30,
@@ -1,5 +1,8 @@
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models;
[EftEnumConverter]
public enum RadioStationType
{
None,
@@ -2,6 +2,7 @@ using System.Text.Json.Serialization;
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
using SPTarkov.Server.Core.Models.Eft.Profile;
using SPTarkov.Server.Core.Models.Enums;
using SPTarkov.Server.Core.Utils.Json.Converters;
namespace SPTarkov.Server.Core.Models.Spt.Dialog;
@@ -176,6 +177,7 @@ public record ProfileChangeEvent
}
}
[EftEnumConverter]
public enum ProfileChangeEventType
{
TraderSalesSum,
@@ -85,3 +85,10 @@ public class EftEnumConverter<T> : JsonConverter<T>
writer.WritePropertyName(propertyValue.ToString());
}
}
/// <summary>
/// This attribute should be applied to enums which should be added as a converter to the json converter
/// </summary>
[AttributeUsage(AttributeTargets.Enum)]
public class EftEnumConverterAttribute : Attribute
{ }
@@ -34,3 +34,10 @@ public class EftListEnumConverter<T> : JsonConverter<List<T>>
writer.WriteEndArray();
}
}
/// <summary>
/// This attribute should be applied to enums which should be added as a converter to the json converter
/// </summary>
[AttributeUsage(AttributeTargets.Enum)]
public class EftListEnumConverterAttribute : Attribute
{ }
@@ -0,0 +1,8 @@
using System.Text.Json.Serialization;
namespace SPTarkov.Server.Core.Utils.Json.Converters;
public interface IJsonConverterRegistrator
{
public IEnumerable<JsonConverter> GetJsonConverters();
}
@@ -0,0 +1,37 @@
using System.Reflection;
using System.Text.Json.Serialization;
using SPTarkov.DI.Annotations;
namespace SPTarkov.Server.Core.Utils.Json.Converters;
[Injectable]
public class SptJsonConverterRegistrator : IJsonConverterRegistrator
{
public IEnumerable<JsonConverter> GetJsonConverters()
{
return [
new BaseSptLoggerReferenceConverter(),
new ListOrTConverterFactory(),
new DictionaryOrListConverter(),
new EftEnumConverter<LogLevel>(), // Special case, this belongs to a lib.
new BaseInteractionRequestDataConverter(),
..GetGenericJsonConverters()
];
}
private static List<JsonConverter> GetGenericJsonConverters()
{
var enums = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => type.IsEnum && type.GetCustomAttribute<EftEnumConverterAttribute>() != null);
var listEnums = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => type.IsEnum && type.GetCustomAttribute<EftListEnumConverterAttribute>() != null);
var result = enums.Select(e => (JsonConverter) Activator.CreateInstance(typeof(EftEnumConverter<>).MakeGenericType(e))!).ToList();
result.AddRange(listEnums.Select(e => (JsonConverter) Activator.CreateInstance(typeof(EftListEnumConverter<>).MakeGenericType(e))!));
return result;
}
}
@@ -2,75 +2,41 @@ using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Serialization;
using SPTarkov.DI.Annotations;
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.Logging;
using SPTarkov.Server.Core.Models.Spt.Dialog;
using SPTarkov.Server.Core.Utils.Json.Converters;
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
namespace SPTarkov.Server.Core.Utils;
[Injectable(InjectionType.Singleton)]
public class JsonUtil
{
private static JsonSerializerOptions jsonSerializerOptionsNoIndent = new()
private static JsonSerializerOptions? jsonSerializerOptionsNoIndent;
private static JsonSerializerOptions? jsonSerializerOptionsIndented;
public JsonUtil(
IEnumerable<IJsonConverterRegistrator> registrators
)
{
WriteIndented = false,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
Converters =
jsonSerializerOptionsNoIndent = new JsonSerializerOptions
{
new BaseSptLoggerReferenceConverter(),
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 EftEnumConverter<BuffType>(),
new EftEnumConverter<BodyPartColliderType>(),
new EftEnumConverter<BanType>(),
new EftEnumConverter<LogLevel>(),
new EftEnumConverter<LogTextColor>(),
new EftEnumConverter<LogBackgroundColor>(),
WriteIndented = false,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
UnmappedMemberHandling = JsonUnmappedMemberHandling.Disallow,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
};
new EftListEnumConverter<EquipmentSlots>(),
new EftListEnumConverter<PlayerSide>(),
new EftListEnumConverter<DamageType>(),
new BaseInteractionRequestDataConverter()
foreach (var registrator in registrators)
{
foreach (var converter in registrator.GetJsonConverters())
{
jsonSerializerOptionsNoIndent.Converters.Add(converter);
}
}
};
protected static JsonSerializerOptions jsonSerializerOptionsIndented = new(jsonSerializerOptionsNoIndent)
{
WriteIndented = true
};
jsonSerializerOptionsIndented = new JsonSerializerOptions(jsonSerializerOptionsNoIndent)
{
WriteIndented = true
};
}
/// <summary>
/// Convert JSON into an object
@@ -165,44 +131,4 @@ public class JsonUtil
{
return obj == null ? null : JsonSerializer.Serialize(obj, type, indented ? jsonSerializerOptionsIndented : jsonSerializerOptionsNoIndent);
}
protected static void AddConverter(JsonSerializerOptions options, JsonConverter newConverter)
{
if (options.Converters.All(c => c.GetType() != newConverter.GetType()))
{
// Doesn't exist, add
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;
}
}
}