If your game has any networked features at all, you are most likely using JSON. It's a convenient format for moving data around in general.
std::string(TCHAR_TO_ANSI(*MyFString()))
ANSI_TO_TCHAR(MyThirdPartyJson.dump().c_str())
I've also seen developers try to write their own UE4 JSON convenience functions, but these often get coupled into whatever the specific developer wants to do with the JSON and are not general-purpose.
My goal here is to try to save other developers the pain I experienced with using Unreal Engine 4's native JSON libraries (and the pain caused by trying to get around them) by sharing this guide to help you get started more quickly. I hope the Unreal Engine community in general will benefit by increasing our efficiency and confidence to work with JSON natively in Unreal Engine, especially with the rise in mobile and networked gaming, and as more people of all experience levels use Unreal Engine for game development.
Setup
Of course you need to include the header:
#include "Json.h"
PublicDependencyModuleNames.AddRange(new string[] {
"Core",
// ... your other dependencies
"Json",
});
Serialization
JSON Object
MyJson->SetStringField("MyStringFieldKey", FString("MyStringFieldValue"));
MyJson->SetNumberField("MyNumberFieldKey", 42);
FString MyJsonFString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&MyJsonFString);
FJsonSerializer::Serialize(MyJson.ToSharedRef(), Writer);
JSON Array
TArray<TSharedPtr<FJsonValue>> MyJsonArray;
// Put some data in the JSON array
for (auto& Element : MyFNameArray)
{
MyJsonArray.Add(MakeShareable(new FJsonValueString(Element.ToString())));
}
FString MyJsonFString;
TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&MyJsonFString);
FJsonSerializer::Serialize(MyJsonArray, Writer);
Deserialization
JSON Object
FString MyJsonFString; // An FString containing a serialized JSON string
TSharedPtr<FJsonObject> MyJson = MakeShareable(new FJsonObject);
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(&MyJsonFString);
if (!FJsonSerializer::Deserialize(Reader, MyJson))
{
// The deserialization failed, handle this case
}
else
{
int MyNumberFieldValue = MyJson->GetNumberField("MyNumberFieldKey");
}
JSON Array
FString MyJsonFString; // An FString containing a serialized JSON string
TArray<TSharedPtr<FJsonValue>> MyJsonArray;
TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(&MyJsonFString);
if (!FJsonSerializer::Deserialize(MyJsonArray, MyJson))
{
// The deserialization failed, handle this case
}
else
{
// Can use or iterate through MyJsonArray
}
Iteration
Iterating through a JSON object is fairly simple, if poorly-documented. Unreal Engine often demands its users to figure things out for themselves. Now you won't have to 😉.JSON Object
TSharedPtr<FJsonObject> MyJson = MakeShareable(new FJsonObject);
TMap<FString, TSharedPtr<FJsonValue>> JsonValues = MyJson->Values;
for (const auto& Element : JsonValues)
{
FString FieldName = Element.Key;
TSharedPtr<FJsonValue> FieldValue = Element.Value;
}
TSharedPtr<FJsonObject> MyJson = MakeShareable(new FJsonObject);
TMap<FString, TSharedPtr<FJsonValue>> JsonValues = MyJson->Values;
for (const auto& Element : JsonValues)
{
FString FieldName = Element.Key;
TSharedPtr<FJsonValue> FieldValue = Element.Value;
}
A JSON array in UE4 is just a TArray<TSharedPtr<FJsonValue>>, which can be iterated through as a normal TArray.
JSON Array
TArray<TSharedPtr<FJsonValue>> MyJsonArray;
for (const auto& Element : MyJsonArray)
{
FString MyStringElement = Element->AsString();
}
In conclusion, I hope I've explained the benefit of using Unreal Engine's native JSON libraries rather than trying to go around them. I hope this blog post can be a helpful resource for anyone trying to use JSON in Unreal Engine. In the long term I believe we will all benefit as users and developers of Unreal Engine and provide optimal experiences for our players if we try to work with UE4's native formats as much as possible.
I have my Json inside Result FString but if I use &Result here:
ReplyDeleteTSharedRef> Reader = TJsonReaderFactory<>::Create(&Result);
compiler fails ...but If I remove the & it compiles but I dont get the data.
FString Result;
TSharedPtr JsonValue;
TSharedPtr MyJson = MakeShareable(new FJsonObject);
TSharedRef> Reader = TJsonReaderFactory<>::Create(Result);
if (FJsonSerializer::Deserialize(Reader,MyJson))
{
avatarId = MyJson->GetNumberField("avatarId");
birthDate = MyJson->GetStringField("birthDate");
gender = MyJson->GetNumberField("gender");
playerID = MyJson->GetStringField("id");
nickname = MyJson->GetStringField("nickname");
}
This post saved me so much time and grief! Thank you so much!
ReplyDeleteThank you for the kind words!
DeleteThank you for putting this together? @Eldany, this code works for me:
ReplyDeleteFString DrifterJSON = "";
TSharedPtr MyJson = MakeShareable(new FJsonObject);
TArray> MyJsonArray;
TSharedRef> Reader = TJsonReaderFactory<>::Create(DrifterJSON);
Sorry I meant to put a ! not a ? lol. This helps tremendously.
DeleteOne other note: When iterating through the FJsonObject, I had to get the "key" and "values" from the Element object like so:
DeleteElement.Key
Element.Value
The Key and Value are not functions, they are properties.
Awesome thanks for the catch! I've updated the example
DeleteCompiles, but fails during linking. Can you help? Are you on Discord maybe?
ReplyDeleteHey @qus, did you add "Json" in your build.cs as mentioned in the guide?
Delete