mirror of
https://github.com/JKorf/CryptoExchange.Net
synced 2025-06-07 16:06:15 +00:00
Fixed System.Text.Json ArrayConverter not passing serializer options to nested deserialization, fixed creating new serializer options each time a JsonConverter attribute is encountered
This commit is contained in:
parent
17f1560310
commit
1aed9f0c67
@ -38,7 +38,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
private class ArrayConverterInner<T> : JsonConverter<T>
|
private class ArrayConverterInner<T> : JsonConverter<T>
|
||||||
{
|
{
|
||||||
private static readonly ConcurrentDictionary<Type, List<ArrayPropertyInfo>> _typeAttributesCache = new ConcurrentDictionary<Type, List<ArrayPropertyInfo>>();
|
private static readonly ConcurrentDictionary<Type, List<ArrayPropertyInfo>> _typeAttributesCache = new ConcurrentDictionary<Type, List<ArrayPropertyInfo>>();
|
||||||
|
private static readonly ConcurrentDictionary<Type, JsonSerializerOptions> _converterOptionsCache = new ConcurrentDictionary<Type, JsonSerializerOptions>();
|
||||||
|
|
||||||
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
|
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
@ -108,7 +108,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
return default;
|
return default;
|
||||||
|
|
||||||
var result = Activator.CreateInstance(typeToConvert);
|
var result = Activator.CreateInstance(typeToConvert);
|
||||||
return (T)ParseObject(ref reader, result, typeToConvert);
|
return (T)ParseObject(ref reader, result, typeToConvert, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsSimple(Type type)
|
private static bool IsSimple(Type type)
|
||||||
@ -148,7 +148,7 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static object ParseObject(ref Utf8JsonReader reader, object result, Type objectType)
|
private static object ParseObject(ref Utf8JsonReader reader, object result, Type objectType, JsonSerializerOptions options)
|
||||||
{
|
{
|
||||||
if (reader.TokenType != JsonTokenType.StartArray)
|
if (reader.TokenType != JsonTokenType.StartArray)
|
||||||
throw new Exception("Not an array");
|
throw new Exception("Not an array");
|
||||||
@ -175,15 +175,24 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
object? value = null;
|
object? value = null;
|
||||||
if (attribute.JsonConverterType != null)
|
if (attribute.JsonConverterType != null)
|
||||||
{
|
{
|
||||||
// Has JsonConverter attribute
|
if (!_converterOptionsCache.TryGetValue(attribute.JsonConverterType, out var newOptions))
|
||||||
var options = new JsonSerializerOptions();
|
{
|
||||||
options.Converters.Add((JsonConverter)Activator.CreateInstance(attribute.JsonConverterType));
|
var converter = (JsonConverter)Activator.CreateInstance(attribute.JsonConverterType);
|
||||||
value = JsonDocument.ParseValue(ref reader).Deserialize(targetType, options);
|
newOptions = new JsonSerializerOptions
|
||||||
|
{
|
||||||
|
NumberHandling = SerializerOptions.WithConverters.NumberHandling,
|
||||||
|
PropertyNameCaseInsensitive = SerializerOptions.WithConverters.PropertyNameCaseInsensitive,
|
||||||
|
Converters = { converter },
|
||||||
|
};
|
||||||
|
_converterOptionsCache.TryAdd(attribute.JsonConverterType, newOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
value = JsonDocument.ParseValue(ref reader).Deserialize(targetType, newOptions);
|
||||||
}
|
}
|
||||||
else if (attribute.DefaultDeserialization)
|
else if (attribute.DefaultDeserialization)
|
||||||
{
|
{
|
||||||
// Use default deserialization
|
// Use default deserialization
|
||||||
value = JsonDocument.ParseValue(ref reader).Deserialize(targetType);
|
value = JsonDocument.ParseValue(ref reader).Deserialize(targetType, options);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -194,11 +203,14 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
JsonTokenType.True => true,
|
JsonTokenType.True => true,
|
||||||
JsonTokenType.String => reader.GetString(),
|
JsonTokenType.String => reader.GetString(),
|
||||||
JsonTokenType.Number => reader.GetDecimal(),
|
JsonTokenType.Number => reader.GetDecimal(),
|
||||||
JsonTokenType.StartObject => JsonSerializer.Deserialize(ref reader, attribute.TargetType),
|
JsonTokenType.StartObject => JsonSerializer.Deserialize(ref reader, attribute.TargetType, options),
|
||||||
_ => throw new NotImplementedException($"Array deserialization of type {reader.TokenType} not supported"),
|
_ => throw new NotImplementedException($"Array deserialization of type {reader.TokenType} not supported"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetType.IsAssignableFrom(value?.GetType()))
|
||||||
|
attribute.PropertyInfo.SetValue(result, value == null ? null : value);
|
||||||
|
else
|
||||||
attribute.PropertyInfo.SetValue(result, value == null ? null : Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture));
|
attribute.PropertyInfo.SetValue(result, value == null ? null : Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,11 @@ namespace CryptoExchange.Net.Converters.SystemTextJson
|
|||||||
var info = $"Deserialize JsonException: {ex.Message}, Path: {ex.Path}, LineNumber: {ex.LineNumber}, LinePosition: {ex.BytePositionInLine}";
|
var info = $"Deserialize JsonException: {ex.Message}, Path: {ex.Path}, LineNumber: {ex.LineNumber}, LinePosition: {ex.BytePositionInLine}";
|
||||||
return new CallResult<object>(new DeserializeError(info, OriginalDataAvailable ? GetOriginalString() : "[Data only available when OutputOriginal = true in client options]"));
|
return new CallResult<object>(new DeserializeError(info, OriginalDataAvailable ? GetOriginalString() : "[Data only available when OutputOriginal = true in client options]"));
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var info = $"Deserialize unknown Exception: {ex.Message}";
|
||||||
|
return new CallResult<object>(new DeserializeError(info, OriginalDataAvailable ? GetOriginalString() : "[Data only available when OutputOriginal = true in client options]"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user