Hi, I have found a core uobject issue trying to serialize ustructs to and from json, where a delegate uproperty, if unbound, cannot be deserialized back into the struct.
I have tracked the problem to DelegatePropertyTools::ImportDelegateFromText (UE5\Engine\Source\Runtime\CoreUObject\Private\UObject\PropertyHelper.cpp) which fails to handle the input string “(null).None” correctly.
It seems to me this is a regression tied to the CL 43574260, https://github.com/EpicGames/UnrealEngine/commit/96801b1961946f02d6c12152c3cb32074d25a965
I have provided code snippets which can reproduce the problem. My current workaround is to simply check the null string case at the top of the import function, but I’d appreciate you provide a proper fix.
Could you please elaborate on the types of path formats this function is supposed to handle? I was confused that the buffer iteration stops on the comma character, along with the dot and parentheses. What path format includes a comma in this case?
Thank you.
[Attachment Removed]
Steps to Reproduce
DECLARE_DYNAMIC_DELEGATE(FTestDelegate);
// Simple struct with a delegate property
USTRUCT()
struct FTestStruct
{
GENERATED_BODY()
UPROPERTY()
int32 TestInt1 = 0;
UPROPERTY()
FTestDelegate DelegateProperty;
UPROPERTY()
int32 TestInt2 = 0;
};
// Serialise the struct to json and back to repro the issue.
FTestStruct TestStruct;
TestStruct.TestInt1 = 1;
TestStruct.DelegateProperty.Unbind();
TestStruct.TestInt2 = 2;
FString JsonTxt;
bool bSuccess1 = FJsonObjectConverter::UStructToJsonObjectString(TestStruct.StaticStruct(), &TestStruct, JsonTxt);
FTestStruct TestStruct2;
TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(JsonTxt);
bool bSuccess2 = FJsonSerializer::Deserialize(JsonReader, JsonObject);
bool bSuccess3 = FJsonObjectConverter::JsonObjectToUStruct(JsonObject.ToSharedRef(), TestStruct2.StaticStruct(), &TestStruct2);
UE_LOG(LogTemp, Warning, TEXT("JsonTxt=%s"), *JsonTxt);
UE_LOG(LogTemp, Warning, TEXT("Success = %d, %d, %d"), bSuccess1, bSuccess2, bSuccess3);
UE_LOG(LogTemp, Warning, TEXT("TestInt1=%d, TestInt2=%d"), TestStruct2.TestInt1, TestStruct2.TestInt2);
// Output:
// JsonTxt={
// "testInt1": 1,
// "delegateProperty": "(null).None",
// "testInt2": 2
// }
// Success = 1, 1, 0
// TestInt1=1, TestInt2=0
// Null delegate property failed to deserialise and the rest of json is skipped as a result (TestInt2 left at 0).
[Attachment Removed]
Hi, thanks for the heads-up. I’ll get it fixed and post back here.
The path format doesn’t include commas - it’s intended to match to the separators between property values in a struct, e.g. as exported by ScriptStruct->ExportText. The JSON path goes through a DOM so the strings being parsed for the delegate are already self-contained.
Steve
[Attachment Removed]
The fix is visible here and should easily be integratable:
https://github.com/EpicGames/UnrealEngine/commit/466b47f578c8bb2ffbfb338e61b3e6a546ea5251
Hope this works for you, sorry for the trouble!
Steve
[Attachment Removed]