Parsing json array of objects

Hi All,

I’m trying to set up communication between a game and a PHP Powered API/Backend.
For this i’m using json to communicate and I’m getting pretty far. Now however i’m trying to parse an array of json objects and i’m not quite sure where to start.

So far, I’ve only worked with parsing an array of integers, strings etc. but never an array of json objects.

My target json input would look something like this:

{
“characters”:[
{
“id”:1,
“Name”:“Test character #1”,
“faction_id”:1
},
{
“id”:2,
“Name”:“Test character #2”,
“faction_id”:1
},
{
“id”:3,
“Name”:“Test character #3”,
“faction_id”:1
}
],
“factions”:[
{
“id”:1,
“Name”:“Test faction #1
}
]
}

So far i’ve only worked with Array of string objects for example, which I can retrieve using:

TArray > nameArray = JsonParsed->GetArrayField(“names”);

And then loop over that. I haven’t been able to find a comparable function used to get sub object.
What would be the correct way to do get, forexample, jsonobject.characters[0].name?

Hey Dratone,

I just figured something out. In case you haven’t already, I’ll just put what I did:

So the first thing I needed was a json array string like the ones you have under “characters” and “factions”:

[
    {
        "id": 1,
        "Name": "Test character #1",
        "faction_id": 1
    },
    {
        "id": 2,
        "Name": "Test character #2",
        "faction_id": 1
    },
    {
        "id": 3,
        "Name": "Test character #3",
        "faction_id": 1
    }
]

I made a USTRUCT that contains the values for each json object in the array:

USTRUCT()
struct FCharacterInfo
{
	GENERATED_USTRUCT_BODY()

	UPROPERTY()
	int32 id;

	UPROPERTY()
	FString Name;

	UPROPERTY()
	int32 faction_id;
};

Then to get a TArray containing your FCharacterInfo elements, do the following:

TArray<FCharacterInfo> data;
FJsonObjectConverter::JsonArrayStringToUStruct(JsonArrayString, &data, 0, 0);

It is very important to make your UPROPERTY’s in your USTRUCT the same name as the json keys because this is how Unreal knows which fields to populate with which values.

Hope this helps somewhat. Good luck!

-Marc

1 Like

Thanks Marc!

I’ll try this asap - about to create a new part where I’ll need this.
Will report back when I’ve tried it.

Hey Dratone,

Did this work for you?

FWIW I’m loading a bunch of non UObjects via JSON. Some pointers below:

	TSharedRef < TJsonReader<> > jsonReader = TJsonReaderFactory<>::Create(tmp);

tmp being a string that you’ve loaded your data into.

TSharedPtr<FJsonObject> jsonObject = MakeShareable(new FJsonObject());
		if (!FJsonSerializer::Deserialize(jsonReader, jsonObject))
		{
			Errorf(_T("FJsonSerializer::Deserialize failed for '%s'"), *rDescFileName);
			return false;
		}
		ReadJSon(*jsonObject.Get());

Then each class implements some form of ReadJSon:

void ModeReference::ReadJSon(FJsonObject &jsonObject)
{
	ModeName = jsonObject.GetStringField(TEXT("ModeName"));

	READ_JSON_ARRAY(jsonObject, RemapLists, ReadJSon);
}

READ_JSON_ARRAY is a macro I put together after writing a few dozen variations on the read array theme:

#define READ_NAMED_JSON_ARRAY(jsonobject, arrayname, arraydataname, readfunc)\
	{\
		FString tmpString(#arraydataname);\
		const TArray< TSharedPtr < FJsonValue > > &tmpJSonArray = jsonobject.GetArrayField(tmpString);\
		arrayname.Reset(tmpJSonArray.Num());\
		arrayname.AddDefaulted(tmpJSonArray.Num());\
		for (int i = 0; i < tmpJSonArray.Num(); i++) {\
			arrayname[i].readfunc(*tmpJSonArray[i]->AsObject().Get());\
		}\
	}

#define READ_JSON_ARRAY(jsonobject, arrayname, readfunc)\
	READ_NAMED_JSON_ARRAY(jsonobject, arrayname, arrayname, readfunc)

I have polymorphic variations on this too based on a common classname variable in the JSon that is added from my editor and some Factory classes.

Just to clarify the two macros allow you to shorthand where your C++ and JSon field names match, or specify both separately if they differ. readfunc is the function name in the sub array object type that takes in a JSon object. For instance:

 void ModeReference::ReadJSon(FJsonObject &jsonObject)

Many thanks for this topic! It was helpful a lot!

I have an issue with parsing. Basically JSON fields need to have key name, when encoding the json string I’m getting key name first. Like this:

Unable to parse. json=[{“FPerkInfo”:"[\t\n\t\t{\n\t\t\t"Name"…

I think that it can’t parse because of the key name. Is there any way to remove it? Or I’m doing it wrong when using JsonArrayStringToUStruct.