So to preface this, I have very little experience with C++, so it could be something super obvious that I am completely oblivious too…
I am using UE4.27
I am working on a little plugin to use in a bunch of my games, and I needed blueprint json functionality. I decided I would try doing this on my own instead of using the Epic json blueprint plugin so that my own plugin wouldn’t be dependant on another.
So to get myself started, I took some of the function code from Epic’s json plugin and pasted it into my own blueprint function library. It compiles fine, but when I use any of the function in editor via blueprints, the editor crashes.
.h File:
#pragma once
#include "CoreMinimal.h"
#include "JsonObjectWrapper.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "CE_EditorJsonFunctions.generated.h"
/**
*
*/
UCLASS(BlueprintType)
class CABBEAST_EDITOR_API UCE_EditorJsonFunctions : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
// Get json object from a json string
UFUNCTION(BlueprintCallable, Category="CE Editor Json Functions", meta = (WorldContext="WorldContextObject", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", DisplayName="Load Json from String"))
static UPARAM(DisplayName="Success") bool FromString(UObject* WorldContextObject, const FString& JsonString, UPARAM(DisplayName="JsonObject") FJsonObjectWrapper& OutJsonObject);
// Create a json object from a string
UFUNCTION(BlueprintCallable, Category="CE Editor Json Functions", meta = (DisplayName = "Get Json String"))
static UPARAM(DisplayName="Success") bool ToString(const FJsonObjectWrapper& JsonObject, UPARAM(DisplayName="String") FString& OutJsonString);
// Get json object from external file
UFUNCTION(BlueprintCallable, Category="CE Editor Json Functions", meta = (WorldContext="WorldContextObject", HidePin = "WorldContextObject", DefaultToSelf = "WorldContextObject", DisplayName="Load Json from File"))
static UPARAM(DisplayName="Success") bool FromFile(UObject* WorldContextObject, const FFilePath& File, UPARAM(DisplayName="JsonObject") FJsonObjectWrapper& OutJsonObject);
// Check if a field exists in json object
UFUNCTION(BlueprintCallable, Category="CE Editor Json Functions")
static UPARAM(DisplayName="Success") bool HasField(const FJsonObjectWrapper& JsonObject, const FString& FieldName);
// Get all field names in a json object
UFUNCTION(BlueprintCallable, Category="CE Editor Json Functions")
static UPARAM(DisplayName="Success") bool GetFieldNames(const FJsonObjectWrapper& JsonObject, TArray<FString>& FieldNames);
// Get a bool field from a json object
UFUNCTION(BlueprintCallable, Category="CE Editor Json Functions")
static UPARAM(DisplayName="Success") bool GetBoolField(const FJsonObjectWrapper& JsonObject, const FString& FieldName, bool& FieldValue);
// Set a bool field in a json object
UFUNCTION(BlueprintCallable, Category="CE Editor Json Functions")
static UPARAM(DisplayName="Success") bool SetBoolField(const FJsonObjectWrapper& JsonObject, const FString FieldName, const bool FieldValue);
private:
/** FieldName only used for logging, SrcValue should be the resolved field. */
static bool JsonFieldToProperty(const FString& FieldName, const FJsonObjectWrapper& SourceObject, FProperty* TargetProperty, void* TargetValuePtr);
// If FieldName empty, Object created as root, or created with name "Value" otherwise.
static bool PropertyToJsonField(const FString& FieldName, FProperty* SourceProperty, const void* SourceValuePtr, FJsonObjectWrapper& TargetObject);
};
.cpp File:
#include "CE_EditorJsonFunctions.h"
#include "JsonObjectConverter.h"
#include "JsonObjectWrapper.h"
#include "Misc/FileHelper.h"
#include "Misc/Paths.h"
#define LOCTEXT_NAMESPACE "CE_EditorJsonFunctions"
bool UCE_EditorJsonFunctions::FromString(UObject* WorldContextObject, const FString& JsonString, FJsonObjectWrapper& OutJsonObject)
{
return OutJsonObject.JsonObjectFromString(JsonString);
}
bool UCE_EditorJsonFunctions::ToString(const FJsonObjectWrapper& JsonObject, FString& OutJsonString)
{
if (!JsonObject.JsonObjectToString(OutJsonString))
{
FFrame::KismetExecutionMessage(TEXT("Failed to convert JSON Object to string"), ELogVerbosity::Error);
return false;
}
return true;
}
bool UCE_EditorJsonFunctions::FromFile(UObject* WorldContextObject, const FFilePath& File, FJsonObjectWrapper& OutJsonObject)
{
if(!FPaths::FileExists(File.FilePath))
{
FFrame::KismetExecutionMessage(*FString::Printf(TEXT("File not found: %s"), *File.FilePath), ELogVerbosity::Error);
return false;
}
FString JsonString;
if(!FFileHelper::LoadFileToString(JsonString, *File.FilePath))
{
FFrame::KismetExecutionMessage(*FString::Printf(TEXT("Error loading file: %s"), *File.FilePath), ELogVerbosity::Error);
return false;
}
return FromString(WorldContextObject, JsonString, OutJsonObject);
}
bool UCE_EditorJsonFunctions::HasField(const FJsonObjectWrapper& JsonObject, const FString& FieldName)
{
return JsonObject.JsonObject->HasField(FieldName);
}
bool UCE_EditorJsonFunctions::GetFieldNames(const FJsonObjectWrapper& JsonObject, TArray<FString>& FieldNames)
{
FieldNames.Reserve(JsonObject.JsonObject->Values.Num());
for (const TPair<FString, TSharedPtr<FJsonValue>>& Field : JsonObject.JsonObject->Values)
{
FieldNames.Add(Field.Key);
}
return true;
}
bool UCE_EditorJsonFunctions::GetBoolField(const FJsonObjectWrapper &JsonObject, const FString &FieldName, bool& FieldValue)
{
if (!JsonObject.JsonObject->HasField(FieldName))
{
return false;
}
FieldValue = JsonObject.JsonObject->GetBoolField(FieldName);
return true;
}
bool UCE_EditorJsonFunctions::SetBoolField(const FJsonObjectWrapper &JsonObject, const FString FieldName, const bool FieldValue)
{
JsonObject.JsonObject->SetBoolField(FieldName, FieldValue);
return true;
}
bool UCE_EditorJsonFunctions::JsonFieldToProperty(
const FString& FieldName,
const FJsonObjectWrapper& SourceObject,
FProperty* TargetProperty,
void* TargetValuePtr)
{
check(SourceObject.JsonObject.IsValid());
check(TargetProperty && TargetValuePtr);
// Check that field with name exists
const TSharedPtr<FJsonValue> JsonValue = SourceObject.JsonObject->TryGetField(FieldName);
if(!JsonValue.IsValid())
{
FFrame::KismetExecutionMessage(*FString::Printf(TEXT("Field '%s' was not found on the provided JSON object."), *FieldName), ELogVerbosity::Warning);
return false;
}
return FJsonObjectConverter::JsonValueToUProperty(JsonValue, TargetProperty, TargetValuePtr);
}
bool UCE_EditorJsonFunctions::PropertyToJsonField(
const FString& FieldName,
FProperty* SourceProperty,
const void* SourceValuePtr,
FJsonObjectWrapper& TargetObject)
{
check(SourceProperty && SourceValuePtr);
if(!TargetObject.JsonObject.IsValid())
{
TargetObject.JsonObject = MakeShared<FJsonObject>();
}
TargetObject.JsonObject->SetField(FieldName, FJsonObjectConverter::UPropertyToJsonValue(SourceProperty, SourceValuePtr));
return true;
}
#undef LOCTEXT_NAMESPACE
This is one of the many crash logs. For some reason, every crash created 2 crash folders, so there are the two logs:
Plugins.log (114.0 KB)
Plugins.log (77.5 KB)
Any help is massively appreciated! <3