Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Nested JSON in Unreal Engine 4

I have a JSON object that I am getting from my server that looks something like this:

{
    "state":"1",
    "player1": {
        "alias":"Player Name",
        "ready":"0"
    }
}

I am able to get the JSON, parse it into a FJsonObject, and retrieve any number or string in the first level of the JSON object using this code to serialize:

TSharedPtr<FJsonObject> JsonParsed;
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(json);
if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
    //Use JsonParsed

And this code to read strings:

FString AJSONContainer::getStringWithKey(FString key)
{
    return storedJSON->GetStringField(key);
}    

Side Note:

AJSONContainer is just an Actor class that I use to call these functions from Blueprints.


That's all fine and dandy, but when I try to read things from the second level, things don't work.

I wrote this code to get the next level down:

TSharedPtr<FJsonObject> nested = storedJSON->GetObjectField(key);

But all calls to get fields of nested return nothing.

nested->GetStringField(anotherKey); //Nothing

So, for example, with the above JSON, this:

TSharedPtr<FJsonObject> nested = storedJSON->GetObjectField("player1");
FString alias = nested->GetStringField("alias");

alias has no value when I print it to the console.


Am I doing something wrong? Why isn't the second-level JSON working?

like image 584
Liftoff Avatar asked May 20 '15 07:05

Liftoff


People also ask

What is JSON in UE4?

Using Json in Unreal Engine 4 – Part 1 Unreal Engine 4 provides some great JSON utility structures and functions for parsing and creating JSON. It’s a format that’s used a lot for data storage and transmission, especially with web requests. This post is the first part in a short series introducing how to use Json in UE4.

Can you use JSON in Unreal Engine?

JSON Parsing in Unreal Engine 4 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. However, Unreal Engine's native JSON libraries are quite verbose and can be difficult to use.

What is a fjsonobject in UE4?

Each of these name-value pairs are stored inside a Json object, which is essentially what is between the curly braces in a Json string. These Json object is represented with the FJsonObject class in UE4, which is declared as such:

What are container classes in Unreal Engine 4 (UE4)?

The simplest container class in Unreal Engine 4 (UE4) is TArray. TArray is responsible for the ownership and organization of a sequence of other objects (called "elements") of the same type.


1 Answers

Don't know if you got it sorted out, but I found a pretty nasty function that works for nested objects and, also, for arrays altogether. And it gives you a USTRUCT, so you don't have to use the functions that get values by Keys (I don't like them since they're very error prone). Instead, you'll have type safety!

FJsonObjectConverter::JsonObjectStringToUStruct

Here are the docs and another question answered on UE4 AnswerHub

Basically, you create the target USTRUCT (or USTRUCTs for nested JSONs), mark all properties with UPROPERTY, so Unreal knows their names, and use this function. It will copy the values by matchmaking them. It copies even the arrays! =D

Example

I'll call the JSON FString to be deserialized Json and it's structure is like the one below. It contains a nested object and an array, to make things interesting.

{
    "nested" : {
        "id" : "654asdf",
        "name" : "The Name"
    },
    "foo" : "foobar",
    "bar_arr" : [
        { "barfoo" : "asdf" },
        { "barfoo" : "qwer" }
    ]
}

Before converting, we need to create the USTRUCTs from inside out (so we can reference inner on the outer). Remember to always use F for struct names.

USTRUCT()
struct FNested
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY()
    FString id;

    UPROPERTY()
    FString name;
};

USTRUCT()
struct FBar
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY()
    FString barfoo;
};

USTRUCT()
struct FJsonData
{
    GENERATED_USTRUCT_BODY()

    UPROPERTY()
    FNested nested;

    UPROPERTY()
    FString foo;

    UPROPERTY()
    TArray<FBar> bar_arr;
};

The conversion will go like this:

FJsonData JsonData;
FJsonObjectConverter::JsonObjectStringToUStruct<FJsonData>(
    Json,
    &JsonData,
    0, 0);

Now, you are able to access all the properties as in standard C++ structs. Eg., to access one of the barfoos:

FString barfoo0 = JsonData.bar_arr[0].barfoo;

I have not tested it with int and float in the JSON, but since it copies even arrays, I believe that would work also.

like image 81
Rodrigo Villani Avatar answered Sep 24 '22 00:09

Rodrigo Villani