Deserialize readers directly

- Saves quite a bit of time on DB load
This commit is contained in:
Archangel
2025-02-17 15:08:46 +01:00
parent 924fff686d
commit cfca1e221f
5 changed files with 51 additions and 80 deletions
@@ -34,11 +34,7 @@ public class ArrayToObjectFactoryConverter : JsonConverterFactory
reader.Read();
return default;
case JsonTokenType.StartObject:
using (var jsonDocument = JsonDocument.ParseValue(ref reader))
{
var jsonText = jsonDocument.RootElement.GetRawText();
return JsonSerializer.Deserialize<T>(jsonText);
}
return JsonSerializer.Deserialize<T>(ref reader, options);
}
return default;
@@ -48,7 +44,8 @@ public class ArrayToObjectFactoryConverter : JsonConverterFactory
{
if (value == null)
{
JsonSerializer.Serialize(writer, new List<object>(), options);
writer.WriteStartArray();
writer.WriteEndArray();
}
else
{
@@ -20,10 +20,8 @@ public class BaseInteractionRequestDataConverter : JsonConverter<BaseInteraction
{
public override BaseInteractionRequestData? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
using var jsonDocument = JsonDocument.ParseValue(ref reader);
var jsonText = jsonDocument.RootElement.GetRawText();
var value = JsonSerializer.Deserialize<BaseInteractionRequestData>(jsonText);
return ConvertToCorrectType(value, jsonText);
var value = JsonSerializer.Deserialize<BaseInteractionRequestData>(ref reader, options);
return ConvertToCorrectType(value, reader.GetString());
}
private BaseInteractionRequestData? ConvertToCorrectType(BaseInteractionRequestData? value, string jsonText)
@@ -17,22 +17,7 @@ public class EftListEnumConverter<T> : JsonConverter<List<T>>
{
if (reader.TokenType == JsonTokenType.StartArray)
{
using (var jsonDocument = JsonDocument.ParseValue(ref reader))
{
var jsonText = jsonDocument.RootElement.GetRawText();
jsonText = jsonText.Replace("[", "").Replace("]", "");
var list = new List<T>();
if (!string.IsNullOrEmpty(jsonText))
{
foreach (var str in jsonText.Split(","))
{
var newStr = str.Replace("\r", "").Replace("\n", "").Trim();
list.Add(JsonSerializer.Deserialize<T>(newStr, options));
}
}
return list;
}
return JsonSerializer.Deserialize<List<T>>(ref reader, _options);
}
throw new JsonException();
@@ -24,26 +24,16 @@ public class ListOrTConverter<T> : JsonConverter<ListOrT<T>?>
{
case JsonTokenType.String:
case JsonTokenType.Number:
using (var jsonDocument = JsonDocument.ParseValue(ref reader))
{
var jsonText = jsonDocument.RootElement.GetRawText();
var value = JsonSerializer.Deserialize<T>(jsonText, options);
return new ListOrT<T>(null, value);
}
var singleValue = JsonSerializer.Deserialize<T>(ref reader, options);
return new ListOrT<T>(null, singleValue);
case JsonTokenType.StartArray:
using (var jsonDocument = JsonDocument.ParseValue(ref reader))
{
var jsonText = jsonDocument.RootElement.GetRawText();
var list = JsonSerializer.Deserialize<List<T>>(jsonText, options);
return new ListOrT<T>(list, default);
}
var list = JsonSerializer.Deserialize<List<T>>(ref reader, options);
return new ListOrT<T>(list, default);
case JsonTokenType.StartObject:
using (var jsonDocument = JsonDocument.ParseValue(ref reader))
{
var jsonText = jsonDocument.RootElement.GetRawText();
var obj = JsonSerializer.Deserialize<T>(jsonText, options);
return new ListOrT<T?>(null, obj);
}
var obj = JsonSerializer.Deserialize<T>(ref reader, options);
return new ListOrT<T>(null, obj);
default:
throw new Exception($"Unable to translate object type {reader.TokenType} to ListOrT<T>.");
}
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -18,47 +19,47 @@ public class StringToNumberFactoryConverter : JsonConverterFactory
private class StringToNumberConverter<T> : JsonConverter<T>
{
private static readonly MethodInfo? stringParseMethod;
static StringToNumberConverter()
{
// Do reflection only once to get parse
var underlyingType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
stringParseMethod = underlyingType.GetMethod("Parse", [typeof(string)]);
}
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
var value = reader.GetString();
if (string.IsNullOrWhiteSpace(value) || value == "__REPLACEME__")
{
return default;
}
try
{
var underlyingType = Nullable.GetUnderlyingType(typeToConvert) ?? typeToConvert;
if (stringParseMethod != null)
{
return (T) stringParseMethod.Invoke(null, [value]);
}
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to parse '{value}' into {typeToConvert.Name}, returning null.");
return default;
}
}
switch (reader.TokenType)
{
case JsonTokenType.String:
var value = reader.GetString();
if (string.IsNullOrWhiteSpace(value))
{
return default;
}
var type = typeToConvert;
try
{
if (typeToConvert.IsGenericType &&
typeToConvert.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = typeToConvert.GenericTypeArguments[0];
}
return (T) type.GetMethods()
.First(
m =>
m.Name == "Parse" &&
m.GetParameters().Length == 1 &&
m.GetParameters().First().ParameterType == typeof(string)
)
.Invoke(null, [value]);
}
catch (Exception ex)
{
Debug.WriteLine($"Tried to convert {value} into {type.Name} but failed to parse it, null value will be used instead.");
}
return default;
case JsonTokenType.Number:
using (var jsonDocument = JsonDocument.ParseValue(ref reader))
{
var jsonText = jsonDocument.RootElement.GetRawText().Replace("\"", "");
return JsonSerializer.Deserialize<T>(jsonText);
}
return JsonSerializer.Deserialize<T>(ref reader, options);
case JsonTokenType.Null:
return default;
default: