Browse Source

Added PolymorphicConverter

Kenric Nugteren 2 days ago
parent
commit
12c9946d92
2 changed files with 48 additions and 7 deletions
  1. 38 0
      InABox.Core/Serialization.cs
  2. 10 7
      inabox.wpf/Dashboard/DynamicDashboard.cs

+ 38 - 0
InABox.Core/Serialization.cs

@@ -887,6 +887,44 @@ namespace InABox.Core
     public interface IGlobalJsonConverter
     {
     }
+
+    public class PolymorphicConverter : JsonConverter<object>
+    {
+        public override bool CanConvert(Type typeToConvert)
+        {
+            return typeToConvert.IsInterface || typeToConvert.IsAbstract;
+        }
+
+        public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+        {
+            var dictionary = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(ref reader, options);
+            if (dictionary is null) return null;
+            if(dictionary.TryGetValue("$type", out var typeName))
+            {
+                var type = Type.GetType(typeName.GetString() ?? "")!;
+                dictionary.Remove("$type");
+                var data = JsonSerializer.Serialize(dictionary, options);
+                return JsonSerializer.Deserialize(data, type, options);
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
+        {
+            writer.WriteStartObject();
+            writer.WriteString("$type", value.GetType().AssemblyQualifiedName);
+            var internalSerialisation = JsonSerializer.Serialize(value, options)[1..^1];
+            if (!internalSerialisation.IsNullOrWhiteSpace())
+            {
+                writer.WriteRawValue(internalSerialisation, true);
+            }
+            writer.WriteEndObject();
+        }
+    }
+
     public abstract class CustomJsonConverter<T> : JsonConverter<T>, IGlobalJsonConverter
     {
         protected object? ReadJson(ref Utf8JsonReader reader)

+ 10 - 7
inabox.wpf/Dashboard/DynamicDashboard.cs

@@ -1,10 +1,11 @@
 using InABox.Core;
-using Newtonsoft.Json;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Text;
+using System.Text.Json;
+using System.Text.Json.Serialization;
 using System.Threading.Tasks;
 
 namespace InABox.Wpf.Dashboard;
@@ -20,7 +21,8 @@ public class DynamicDashboard
 
     private string _presenterProperties = "";
 
-    [JsonProperty(Order = 1, PropertyName = "PresenterProperties")]
+    [JsonPropertyOrder(1)]
+    [JsonPropertyName("PresenterProperties")]
     private string PresenterProperties
     {
         get => DataPresenter is not null ? Serialization.Serialize(DataPresenter.Properties) : "";
@@ -30,7 +32,8 @@ public class DynamicDashboard
         }
     }
 
-    [JsonProperty(Order = 2, PropertyName = "PresenterType")]
+    [JsonPropertyOrder(2)]
+    [JsonPropertyName("PresenterType")]
     private Type? PresenterType
     {
         get => DataPresenter?.GetType();
@@ -83,21 +86,21 @@ public static class DynamicDashboardUtils
         return _presenterTypes;
     }
 
-    private static JsonSerializerSettings SerializationSettings()
+    private static JsonSerializerOptions SerializationSettings()
     {
         var settings = Serialization.CreateSerializerSettings();
-        settings.TypeNameHandling = TypeNameHandling.Auto;
+        settings.Converters.Add(new PolymorphicConverter());
         return settings;
     }
 
     public static string Serialize(DynamicDashboard data)
     {
-        return JsonConvert.SerializeObject(data, typeof(DynamicDashboard), SerializationSettings());
+        return JsonSerializer.Serialize(data, typeof(DynamicDashboard), SerializationSettings());
     }
 
     public static DynamicDashboard? Deserialize(string? json)
     {
         if (json.IsNullOrWhiteSpace()) return null;
-        return JsonConvert.DeserializeObject<DynamicDashboard>(json, SerializationSettings())!;
+        return JsonSerializer.Deserialize<DynamicDashboard>(json, SerializationSettings())!;
     }
 }