FJsonSerializer::Deserialize bug with TArray

Hello!
Straight to the point;
I’m serializing an object in C# to Json, It looks like this:

List<ServerListItem> ServerList;
string result = JsonConvert.SerializeObject(ServerList);

I then try to Deserialize the same string with FJsonSerializer like this:

    TArray<FWServer> servers;
	TArray<TSharedPtr<FJsonValue>> JsonParsed;
	TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(someServers);
	if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
	{
		for (int i = 0; i < JsonParsed.Num(); ++i)
		{
			auto item = JsonParsed[i]->AsObject();
			FWServer s = FWServer();
			s.mIpAddress = item->GetStringField("ipAddress");
			s.mPort = item->GetNumberField("Port");
			s.mServerName = item->GetStringField("ServerName");
			servers.Add(s);
		}
	}

Where “someServers” is an FString with the exact same contents as “Result” from c#. With one element the deserialize returns true, with more than one element it returns false.

Thank you.

Matt.

Inside the JsonSerializer.h file it fails at line 194, claiming the EJsonNotation is an Error.
Any idea why?

I ended up hacking my way around it. It seems like Unreal’s Json converter can’t handle arrays atm. This is what I ended up doing;

TArray<FString> serverListSplit;
FString left, right, current;
current = someServers;
current.RemoveFromStart("["); current.RemoveFromEnd("]");
while (current.Split("}", &left, &right))
{
	left += "}";
	right.RemoveFromStart(",");
	current = right;
	serverListSplit.Add(left);
}

TArray<FWServer> servers;
for (int i = 0; i < serverListSplit.Num(); ++i)
{
	TSharedPtr<FJsonObject> JsonParsed = MakeShareable(new FJsonObject());
	TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(serverListSplit[i]);
	if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
	{
		auto item = JsonParsed;

		FWServer s = FWServer();
		s.mIpAddress		= item->GetStringField("ipAddress");
		s.mPort			= item->GetNumberField("Port");
		s.mServerName	= item->GetStringField("ServerName");
	}
}
1 Like

Can you post the string generated in your C# code? This may be a bug in FJsonDeserializer. Arrays should be supported.

Sure thing! Looks like this:

[{ipAddress:"127.0.0.1","Port":"7777","ServerName":"Testing01"},
{ipAddress:"127.0.0.1","Port":"7777","ServerName":"Testing02"}]

This doesn’t work for json output like:
[{“size”:3},{“parts”:[“part1”,“part2”,“part3”]}]

Do you know how to solve this?

Nothing pops out at me, but it appears we are missing a test case with a root array with multiple items. I’ll pop that in, see if it repros and get a fix.

I’ve added test cases for various root array scenario and I wasn’t able to repro your issue.

I then tried to test with the string you provided above and noticed that the ‘ipAddress’ fields don’t have quotes around them. Our parser requires that all field names be quoted.

Thank you! Then there must be an error in how the standard c# JSON serializer serializes JSON. Odd!

Thanks again for taking your time and testing this.

Hello! I have the same problems:
If root node is array, i get " Error: JSON data is invalid"

[
  {
"id": 1,
"name": " 0",
"visible": 1,
"summary": "",
"summaryformat": 1,
"section": 0,
"hiddenbynumsections": 0,
"uservisible": true,
"modules": [
  {
"id": 1,
"url": "http://moodle.local/mod/lesson/view.php?id=1",
"name": "Размножение диаспоры уругвайских тушканчиков",
"instance": 1,
"contextid": 60,
"visible": 1,
"uservisible": true,
"visibleoncoursepage": 1,
"modicon": "http://moodle.local/theme/image.php/_s/boost/lesson/1618901170/icon",
"modname": "lesson",
"modplural": "Лекции",
"availability": null,
"indent": 0,
"onclick": "",
"afterlink": null,
"customdata": """",
"noviewlink": false,
"completion": 1,
"completiondata": {
"state": 0,
"timecompleted": 0,
"overrideby": null,
"valueused": false
}
}
],
},
  {
"id": 2,
"name": " 1",
"visible": 0,
"summary": "",
"summaryformat": 1,
"section": 1,
"hiddenbynumsections": 0,
"uservisible": true,
"modules": [],
}
]

I solved a problem, added code:

    FString dataString = Response->GetContentAsString();
    if (dataString[0] == '[')
    	{
    		dataString = FString("{\"root\":") +dataString + '}';
    	}
    // Process the string
    	if (!FromString(dataString)) {
    		OnGetResult.Broadcast(false, this, EJSONResult::JSONParsingFailed);
    		return;
    	}
//
//
//  
    bool UJsonFieldData::FromString(const FString& dataString) {
    
    
    	TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(dataString);
    
    	// Deserialize the JSON data
    	bool isDeserialized = FJsonSerializer::Deserialize(JsonReader, Data);
    
    	if (!isDeserialized || !Data.IsValid()) {
    		UE_LOG(JSONQueryLog, Error, TEXT("JSON data is invalid! Input:\n'%s'!"), *dataString);
    		return false;
    	}
    
    	return true;
    }