Skip to content

Commit

Permalink
Merge pull request #6353 from elsa-workflows/bug/primitive-array-seri…
Browse files Browse the repository at this point in the history
…alization

Back-port PolymorphicObjectConverter from 3.3
  • Loading branch information
sfmskywalker authored Jan 29, 2025
2 parents 646fb92 + b8f1cfd commit add1bcb
Showing 1 changed file with 33 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonS
if (reader.TokenType != JsonTokenType.StartObject && reader.TokenType != JsonTokenType.StartArray)
return ReadPrimitive(ref reader, newOptions);

var targetType = ReadType(reader);
var targetType = ReadType(reader, options);
if (targetType == null)
return ReadObject(ref reader, newOptions);

Expand Down Expand Up @@ -165,7 +165,25 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp
var newOptions = options.Clone();
var type = value.GetType();

if (type.IsPrimitive || value is string or decimal or DateTimeOffset or DateTime or DateOnly or TimeOnly or JsonElement or Guid or TimeSpan or Uri or Version or Enum)
// If the type is a primitive type or an enumerable of a primitive type, serialize the value directly.
bool IsPrimitive(Type valueType)
{
return type.IsPrimitive
|| valueType == typeof(string)
|| valueType == typeof(decimal)
|| valueType == typeof(DateTimeOffset)
|| valueType == typeof(DateTime)
|| valueType == typeof(DateOnly)
|| valueType == typeof(TimeOnly)
|| valueType == typeof(JsonElement)
|| valueType == typeof(Guid)
|| valueType == typeof(TimeSpan)
|| valueType == typeof(Uri)
|| valueType == typeof(Version)
|| valueType.IsEnum;
}

if (IsPrimitive(type))
{
// Remove the converter so that we don't end up in an infinite loop.
newOptions.Converters.RemoveWhere(x => x is PolymorphicObjectConverterFactory);
Expand Down Expand Up @@ -245,13 +263,10 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp
{
if (shouldWriteTypeField)
{
var typeOptions = newOptions.Clone();
typeOptions.Converters.RemoveWhere(c => c.GetType() != typeof(TypeJsonConverter));

if (typeOptions.Converters.Any())
if (newOptions.Converters.OfType<TypeJsonConverter>().FirstOrDefault() is { } typeJsonConverter)
{
var typeValue = JsonSerializer.Serialize(type, typeOptions).Trim('"');
writer.WriteString(TypePropertyName, typeValue);
writer.WritePropertyName(TypePropertyName);
typeJsonConverter.Write(writer, type, newOptions);
}
else
{
Expand All @@ -263,7 +278,7 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp
writer.WriteEndObject();
}

private Type? ReadType(Utf8JsonReader reader)
private Type? ReadType(Utf8JsonReader reader, JsonSerializerOptions options)
{
if (reader.TokenType != JsonTokenType.StartObject)
return null;
Expand All @@ -278,7 +293,14 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp
if (reader.TokenType == JsonTokenType.PropertyName && reader.ValueTextEquals(TypePropertyName))
{
reader.Read(); // Move to the value of the _type property
typeName = reader.GetString();
if (options.Converters.OfType<TypeJsonConverter>().FirstOrDefault() is { } typeJsonConverter)
{
return typeJsonConverter.Read(ref reader, typeof(Type), options);
}
else
{
typeName = reader.GetString();
}
break;
}

Expand Down Expand Up @@ -308,7 +330,7 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp
}

// If we found the _type property, attempt to resolve the type.
var targetType = typeName != null ? wellKnownTypeRegistry.TryGetType(typeName, out var type) ? type : Type.GetType(typeName) : default;
var targetType = typeName != null ? Type.GetType(typeName) : default;
return targetType;
}

Expand Down

0 comments on commit add1bcb

Please sign in to comment.