Browse Source

added serializer for ValueTuples

Kenric Nugteren 1 week ago
parent
commit
c080d1fb47
1 changed files with 51 additions and 3 deletions
  1. 51 3
      InABox.Core/Serialization.cs

+ 51 - 3
InABox.Core/Serialization.cs

@@ -1,13 +1,13 @@
-using System;
-using System.Collections.Concurrent;
+using InABox.Clients;
+using System;
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Linq;
+using System.Runtime.CompilerServices;
 using System.Text.Json;
 using System.Text.Json.Serialization;
 using System.Text.Json.Serialization.Metadata;
-using InABox.Clients;
 
 namespace InABox.Core
 {
@@ -72,6 +72,7 @@ namespace InABox.Core
             new SortOrderJsonConverter(),
             new MultiQueryRequestConverter(),
             new UserPropertiesJsonConverter(),
+            new ValueTupleJsonConverter(),
             new TypeJsonConverter(),
             new PolymorphicConverter(),
             new ObjectConverter(), // Our fallback, which converts JSON objects into real ones.
@@ -1191,4 +1192,51 @@ namespace InABox.Core
             writer.WriteStringValue(value.AssemblyQualifiedName);
         }
     }
+
+    public class ValueTupleJsonConverter : CustomJsonConverter<object>
+    {
+        public override bool CanConvert(Type typeToConvert)
+        {
+            return typeToConvert.HasInterface<ITuple>() && !typeToConvert.IsClass && !typeToConvert.IsInterface;
+        }
+
+        public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+        {
+            var typeArgs = typeToConvert.GenericTypeArguments;
+            var values = new object?[typeArgs.Length];
+            ReadObject(ref reader, (ref Utf8JsonReader reader, string property) =>
+            {
+                if (property.StartsWith("Item") && int.TryParse(property[4..], out var i) && i - 1 < values.Length)
+                {
+                    values[i - 1] = JsonSerializer.Deserialize(ref reader, typeArgs[i - 1], options);
+                }
+                else if(property == "Rest")
+                {
+                    values[^1] = JsonSerializer.Deserialize(ref reader, typeArgs[^1], options);
+                }
+            });
+            return Activator.CreateInstance(typeToConvert, values);
+        }
+
+        public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options)
+        {
+            if(value is ITuple tuple)
+            {
+                var type = value.GetType();
+
+                writer.WriteStartObject();
+                foreach(var field in type.GetFields())
+                {
+                    writer.WritePropertyName(field.Name);
+                    JsonSerializer.Serialize(writer, field.GetValue(tuple), field.FieldType, options);
+                }
+                writer.WriteEndObject();
+            }
+            else
+            {
+                writer.WriteNullValue();
+                return;
+            }
+        }
+    }
 }