Improve JSON array conversion in ObjectConverter
Refactored ObjectConverter to handle JSON array conversions more robustly, including support for arrays of complex types. Added a `Person` class for unit testing and updated tests to validate the new functionality. Included necessary project reference updates to ensure proper functionality.
This commit is contained in:
parent
9437ab3a3d
commit
0560d11432
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\common\Elsa.Features\Elsa.Features.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Common\Elsa.Common.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -102,15 +102,29 @@ public static class ObjectConverter
|
|||
return jsonElement.Deserialize(targetType, serializerOptions);
|
||||
}
|
||||
|
||||
if (value is JsonNode jsonNode and not JsonArray) // If the value is a JsonNode, we can convert it to the target type. If it's a JsonArray, we let the enumerable conversion logic handle it.
|
||||
if (value is JsonNode jsonNode)
|
||||
{
|
||||
return underlyingTargetType switch
|
||||
if (jsonNode is not JsonArray jsonArray)
|
||||
{
|
||||
{ } t when t == typeof(string) => jsonNode.ToString(),
|
||||
{ } t when t == typeof(ExpandoObject) && jsonNode.GetValueKind() == JsonValueKind.Object => JsonSerializer.Deserialize<ExpandoObject>(jsonNode.ToJsonString()),
|
||||
{ } t when t != typeof(object) || converterOptions?.DeserializeJsonObjectToObject == true => jsonNode.Deserialize(targetType, serializerOptions),
|
||||
_ => jsonNode
|
||||
};
|
||||
return underlyingTargetType switch
|
||||
{
|
||||
{ } t when t == typeof(string) => jsonNode.ToString(),
|
||||
{ } t when t == typeof(ExpandoObject) && jsonNode.GetValueKind() == JsonValueKind.Object => JsonSerializer.Deserialize<ExpandoObject>(jsonNode.ToJsonString()),
|
||||
{ } t when t != typeof(object) || converterOptions?.DeserializeJsonObjectToObject == true => jsonNode.Deserialize(targetType, serializerOptions),
|
||||
_ => jsonNode
|
||||
};
|
||||
}
|
||||
|
||||
// Convert to target type if target type is an array or a generic collection.
|
||||
if (targetType.IsArray || targetType.IsCollectionType())
|
||||
{
|
||||
// The element type of the source array is JsonObject. If the element type of the target array is Object then return the source array as an array of JsonObjects.
|
||||
// Deserializing normally would return an array of JsonElement instead of JsonObject, but we want to keep JsonObject elements:
|
||||
var targetElementType = targetType.IsArray ? targetType.GetElementType()! : targetType.GenericTypeArguments[0];
|
||||
|
||||
if (targetElementType != typeof(object))
|
||||
return jsonArray.Deserialize(targetType, serializerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
if (underlyingSourceType == typeof(string) && !underlyingTargetType.IsPrimitive && underlyingTargetType != typeof(object))
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
namespace Elsa.Workflows.Core.UnitTests.ObjectConversion
|
||||
{
|
||||
public class Person
|
||||
{
|
||||
public double? Age { get; set; }
|
||||
|
||||
public string? Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -283,4 +283,21 @@ public class Tests
|
|||
Assert.Equal("Bob", secondElement["name"]?.ToString());
|
||||
Assert.Equal("25", secondElement["age"]?.ToString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConvertFrom_JsonArrayToArrayOfComplextType_ReturnsArrayOfComplexType()
|
||||
{
|
||||
// Arrange
|
||||
var jsonArrayString = "[{\"name\":\"Alice\",\"age\":30},{\"name\":\"Bob\",\"age\":25}]";
|
||||
var options = new ObjectConverterOptions();
|
||||
|
||||
// Act
|
||||
var result = jsonArrayString.ConvertTo<Person[]>(options);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Equal(2, result.Length);
|
||||
Assert.Equal("Alice", result[0].Name);
|
||||
Assert.Equal("Bob", result[1].Name);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue