diff --git a/Utilities/LibMatrix.DebugDataValidationApi/JsonElementExtensions.cs b/Utilities/LibMatrix.DebugDataValidationApi/JsonElementExtensions.cs
new file mode 100644
index 0000000..c4ed743
--- /dev/null
+++ b/Utilities/LibMatrix.DebugDataValidationApi/JsonElementExtensions.cs
@@ -0,0 +1,147 @@
+using System.Reflection;
+using System.Text.Json;
+using System.Text.Json.Nodes;
+using System.Text.Json.Serialization;
+
+namespace LibMatrix.Extensions;
+
+public static class JsonElementExtensions {
+ public static bool FindExtraJsonElementFields(this JsonElement obj, Type objectType, string objectPropertyName) {
+ if (objectPropertyName == "content" && objectType == typeof(JsonObject))
+ objectType = typeof(StateEventResponse);
+ // if (t == typeof(JsonNode))
+ // return false;
+
+ Console.WriteLine($"{objectType.Name} {objectPropertyName}");
+ var unknownPropertyFound = false;
+ var mappedPropsDict = objectType.GetProperties()
+ .Where(x => x.GetCustomAttribute<JsonPropertyNameAttribute>() is not null)
+ .ToDictionary(x => x.GetCustomAttribute<JsonPropertyNameAttribute>()!.Name, x => x);
+ objectType.GetProperties().Where(x => !mappedPropsDict.ContainsKey(x.Name))
+ .ToList().ForEach(x => mappedPropsDict.TryAdd(x.Name, x));
+
+ foreach (var field in obj.EnumerateObject()) {
+ if (mappedPropsDict.TryGetValue(field.Name, out var mappedProperty)) {
+ //dictionary
+ if (mappedProperty.PropertyType.IsGenericType &&
+ mappedProperty.PropertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) {
+ unknownPropertyFound |= _checkDictionary(field, objectType, mappedProperty.PropertyType);
+ continue;
+ }
+
+ if (mappedProperty.PropertyType.IsGenericType &&
+ mappedProperty.PropertyType.GetGenericTypeDefinition() == typeof(List<>)) {
+ unknownPropertyFound |= _checkList(field, objectType, mappedProperty.PropertyType);
+ continue;
+ }
+
+ if (field.Name == "content" && (objectType == typeof(StateEventResponse) || objectType == typeof(StateEvent))) {
+ unknownPropertyFound |= field.FindExtraJsonPropertyFieldsByValueKind(
+ StateEvent.GetStateEventType(obj.GetProperty("type").GetString()!), // We expect type to always be present
+ mappedProperty.PropertyType);
+ continue;
+ }
+
+ unknownPropertyFound |=
+ field.FindExtraJsonPropertyFieldsByValueKind(objectType, mappedProperty.PropertyType);
+ continue;
+ }
+
+ Console.WriteLine($"[!!] Unknown property {field.Name} in {objectType.Name}!");
+ unknownPropertyFound = true;
+ }
+
+ return unknownPropertyFound;
+ }
+
+ private static bool FindExtraJsonPropertyFieldsByValueKind(this JsonProperty field, Type containerType,
+ Type propertyType) {
+ if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) propertyType = propertyType.GetGenericArguments()[0];
+
+ var switchResult = false;
+ switch (field.Value.ValueKind) {
+ case JsonValueKind.Array:
+ switchResult = field.Value.EnumerateArray().Aggregate(switchResult,
+ (current, element) => current | element.FindExtraJsonElementFields(propertyType, field.Name));
+ break;
+ case JsonValueKind.Object:
+ switchResult |= field.Value.FindExtraJsonElementFields(propertyType, field.Name);
+ break;
+ case JsonValueKind.True:
+ case JsonValueKind.False:
+ return _checkBool(field, containerType, propertyType);
+ case JsonValueKind.String:
+ return _checkString(field, containerType, propertyType);
+ case JsonValueKind.Number:
+ return _checkNumber(field, containerType, propertyType);
+ case JsonValueKind.Undefined:
+ case JsonValueKind.Null:
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+
+ return switchResult;
+ }
+
+ private static bool _checkBool(this JsonProperty field, Type containerType, Type propertyType) {
+ if (propertyType == typeof(bool)) return true;
+ Console.WriteLine(
+ $"[!!] Encountered bool for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!");
+ return false;
+ }
+
+ private static bool _checkString(this JsonProperty field, Type containerType, Type propertyType) {
+ if (propertyType == typeof(string)) return true;
+ // ReSharper disable once BuiltInTypeReferenceStyle
+ if (propertyType == typeof(String)) return true;
+ Console.WriteLine(
+ $"[!!] Encountered string for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!");
+ return false;
+ }
+
+ private static bool _checkNumber(this JsonProperty field, Type containerType, Type propertyType) {
+ if (propertyType == typeof(int) ||
+ propertyType == typeof(double) ||
+ propertyType == typeof(float) ||
+ propertyType == typeof(decimal) ||
+ propertyType == typeof(long) ||
+ propertyType == typeof(short) ||
+ propertyType == typeof(uint) ||
+ propertyType == typeof(ulong) ||
+ propertyType == typeof(ushort) ||
+ propertyType == typeof(byte) ||
+ propertyType == typeof(sbyte))
+ return true;
+ Console.WriteLine(
+ $"[!!] Encountered number for {field.Name} in {containerType.Name}, the class defines {propertyType.Name}!");
+ return false;
+ }
+
+ private static bool _checkDictionary(this JsonProperty field, Type containerType, Type propertyType) {
+ var keyType = propertyType.GetGenericArguments()[0];
+ var valueType = propertyType.GetGenericArguments()[1];
+ valueType = Nullable.GetUnderlyingType(valueType) ?? valueType;
+ Console.WriteLine(
+ $"Encountered dictionary {field.Name} with key type {keyType.Name} and value type {valueType.Name}!");
+
+ return field.Value.EnumerateObject()
+ .Where(key => !valueType.IsPrimitive && valueType != typeof(string))
+ .Aggregate(false, (current, key) =>
+ current | key.FindExtraJsonPropertyFieldsByValueKind(containerType, valueType)
+ );
+ }
+
+ private static bool _checkList(this JsonProperty field, Type containerType, Type propertyType) {
+ var valueType = propertyType.GetGenericArguments()[0];
+ valueType = Nullable.GetUnderlyingType(valueType) ?? valueType;
+ Console.WriteLine(
+ $"Encountered list {field.Name} with value type {valueType.Name}!");
+
+ return field.Value.EnumerateArray()
+ .Where(key => !valueType.IsPrimitive && valueType != typeof(string))
+ .Aggregate(false, (current, key) =>
+ current | key.FindExtraJsonElementFields(valueType, field.Name)
+ );
+ }
+}
\ No newline at end of file
diff --git a/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj b/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj
index 24fd617..3466fb1 100644
--- a/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj
+++ b/Utilities/LibMatrix.DebugDataValidationApi/LibMatrix.DebugDataValidationApi.csproj
@@ -9,8 +9,8 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.0"/>
- <PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0"/>
+ <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.5" />
+ <PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
</ItemGroup>
<ItemGroup>
diff --git a/Utilities/LibMatrix.DevTestBot/Bot/FileStorageProvider.cs b/Utilities/LibMatrix.DevTestBot/Bot/FileStorageProvider.cs
index cc866e6..05b357e 100644
--- a/Utilities/LibMatrix.DevTestBot/Bot/FileStorageProvider.cs
+++ b/Utilities/LibMatrix.DevTestBot/Bot/FileStorageProvider.cs
@@ -1,36 +1,36 @@
-using System.Text.Json;
-using ArcaneLibs.Extensions;
-using LibMatrix.Interfaces.Services;
-using Microsoft.Extensions.Logging;
-
-namespace LibMatrix.ExampleBot.Bot;
-
-public class FileStorageProvider : IStorageProvider {
- private readonly ILogger<FileStorageProvider> _logger;
-
- public string TargetPath { get; }
-
- /// <summary>
- /// Creates a new instance of <see cref="FileStorageProvider" />.
- /// </summary>
- /// <param name="targetPath"></param>
- public FileStorageProvider(string targetPath) {
- new Logger<FileStorageProvider>(new LoggerFactory()).LogInformation("test");
- Console.WriteLine($"Initialised FileStorageProvider with path {targetPath}");
- TargetPath = targetPath;
- if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath);
- }
-
- public async Task SaveObjectAsync<T>(string key, T value) => await File.WriteAllTextAsync(Path.Join(TargetPath, key), value?.ToJson());
-
- public async Task<T?> LoadObjectAsync<T>(string key) => JsonSerializer.Deserialize<T>(await File.ReadAllTextAsync(Path.Join(TargetPath, key)));
-
- public Task<bool> ObjectExistsAsync(string key) => Task.FromResult(File.Exists(Path.Join(TargetPath, key)));
-
- public Task<List<string>> GetAllKeysAsync() => Task.FromResult(Directory.GetFiles(TargetPath).Select(Path.GetFileName).ToList());
-
- public Task DeleteObjectAsync(string key) {
- File.Delete(Path.Join(TargetPath, key));
- return Task.CompletedTask;
- }
-}
\ No newline at end of file
+// using System.Text.Json;
+// using ArcaneLibs.Extensions;
+// using LibMatrix.Interfaces.Services;
+// using Microsoft.Extensions.Logging;
+//
+// namespace LibMatrix.ExampleBot.Bot;
+//
+// public class FileStorageProvider : IStorageProvider {
+// private readonly ILogger<FileStorageProvider> _logger;
+//
+// public string TargetPath { get; }
+//
+// /// <summary>
+// /// Creates a new instance of <see cref="FileStorageProvider" />.
+// /// </summary>
+// /// <param name="targetPath"></param>
+// public FileStorageProvider(string targetPath) {
+// new Logger<FileStorageProvider>(new LoggerFactory()).LogInformation("test");
+// Console.WriteLine($"Initialised FileStorageProvider with path {targetPath}");
+// TargetPath = targetPath;
+// if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath);
+// }
+//
+// public async Task SaveObjectAsync<T>(string key, T value) => await File.WriteAllTextAsync(Path.Join(TargetPath, key), value?.ToJson());
+//
+// public async Task<T?> LoadObjectAsync<T>(string key) => JsonSerializer.Deserialize<T>(await File.ReadAllTextAsync(Path.Join(TargetPath, key)));
+//
+// public Task<bool> ObjectExistsAsync(string key) => Task.FromResult(File.Exists(Path.Join(TargetPath, key)));
+//
+// public Task<List<string>> GetAllKeysAsync() => Task.FromResult(Directory.GetFiles(TargetPath).Select(Path.GetFileName).ToList());
+//
+// public Task DeleteObjectAsync(string key) {
+// File.Delete(Path.Join(TargetPath, key));
+// return Task.CompletedTask;
+// }
+// }
\ No newline at end of file
diff --git a/Utilities/LibMatrix.Utilities.Bot/FileStorageProvider.cs b/Utilities/LibMatrix.Utilities.Bot/FileStorageProvider.cs
index b762937..f723c57 100644
--- a/Utilities/LibMatrix.Utilities.Bot/FileStorageProvider.cs
+++ b/Utilities/LibMatrix.Utilities.Bot/FileStorageProvider.cs
@@ -1,32 +1,32 @@
-using System.Text.Json;
-using ArcaneLibs.Extensions;
-using LibMatrix.Interfaces.Services;
-
-namespace LibMatrix.Utilities.Bot;
-
-public class FileStorageProvider : IStorageProvider {
- public string TargetPath { get; }
-
- /// <summary>
- /// Creates a new instance of <see cref="FileStorageProvider" />.
- /// </summary>
- /// <param name="targetPath"></param>
- public FileStorageProvider(string targetPath) {
- Console.WriteLine($"Initialised FileStorageProvider with path {targetPath}");
- TargetPath = targetPath;
- if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath);
- }
-
- public async Task SaveObjectAsync<T>(string key, T value) => await File.WriteAllTextAsync(Path.Join(TargetPath, key), value?.ToJson());
-
- public async Task<T?> LoadObjectAsync<T>(string key) => JsonSerializer.Deserialize<T>(await File.ReadAllTextAsync(Path.Join(TargetPath, key)));
-
- public Task<bool> ObjectExistsAsync(string key) => Task.FromResult(File.Exists(Path.Join(TargetPath, key)));
-
- public Task<List<string>> GetAllKeysAsync() => Task.FromResult(Directory.GetFiles(TargetPath).Select(Path.GetFileName).ToList());
-
- public Task DeleteObjectAsync(string key) {
- File.Delete(Path.Join(TargetPath, key));
- return Task.CompletedTask;
- }
-}
\ No newline at end of file
+// using System.Text.Json;
+// using ArcaneLibs.Extensions;
+// using LibMatrix.Interfaces.Services;
+//
+// namespace LibMatrix.Utilities.Bot;
+//
+// public class FileStorageProvider : IStorageProvider {
+// public string TargetPath { get; }
+//
+// /// <summary>
+// /// Creates a new instance of <see cref="FileStorageProvider" />.
+// /// </summary>
+// /// <param name="targetPath"></param>
+// public FileStorageProvider(string targetPath) {
+// Console.WriteLine($"Initialised FileStorageProvider with path {targetPath}");
+// TargetPath = targetPath;
+// if (!Directory.Exists(targetPath)) Directory.CreateDirectory(targetPath);
+// }
+//
+// public async Task SaveObjectAsync<T>(string key, T value) => await File.WriteAllTextAsync(Path.Join(TargetPath, key), value?.ToJson());
+//
+// public async Task<T?> LoadObjectAsync<T>(string key) => JsonSerializer.Deserialize<T>(await File.ReadAllTextAsync(Path.Join(TargetPath, key)));
+//
+// public Task<bool> ObjectExistsAsync(string key) => Task.FromResult(File.Exists(Path.Join(TargetPath, key)));
+//
+// public Task<List<string>> GetAllKeysAsync() => Task.FromResult(Directory.GetFiles(TargetPath).Select(Path.GetFileName).ToList());
+//
+// public Task DeleteObjectAsync(string key) {
+// File.Delete(Path.Join(TargetPath, key));
+// return Task.CompletedTask;
+// }
+// }
\ No newline at end of file
diff --git a/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj b/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj
index 89ea5af..6e67373 100644
--- a/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj
+++ b/Utilities/LibMatrix.Utilities.Bot/LibMatrix.Utilities.Bot.csproj
@@ -12,9 +12,9 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0"/>
+ <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/>
- <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0"/>
+ <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.1" />
</ItemGroup>
|