Map In Array

I have been trying to make an array that includes a map with 2 string variables, but apparently that’s not possible so I tried to make custom class and make an array with that class, however I keep getting various errors.

I found a function from the engine, so I copied it and changed it a bit, so I came up with this:

UCLASS()
class UMySQLRow : public TMap<FString, FString>
{
	GENERATED_BODY()
public:

	virtual ~UMySQLRow() {}

	FString operator () (const FString& Key) const
	{
		const FString* Found = Find(Key);
		return Found ? *Found : TEXT("");
	}
};

typedef TArray<UMySQLRow> MySQLRowAll;

and then

UCLASS()
class DRAGGAMENEW_API UMySQL : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

	UFUNCTION(BlueprintCallable, meta = (DisplayName = "Get Data With Map From MySQL", ExpandEnumAsExecs = "SucFail", DataTablePin = "CurveTable"), Category = Database)
	static void GetDataWMap(FString DatabaseName, FString Query, ESuccessFail& SucFail, MySQLRowAll& Results);

};

That one gives me that class TMap could not be found. However, I included “Map.h”.

Making a simple class (without using UCLASS() or GENERATED_BODY()) gives me other errors, but I still can’t get it done.

What I am trying to achieve is getting data from MySQL through blueprints. I want to make a map that uses the column name as key and the column data as the value. Then make an array for all rows.

I made a few updates, I’ve come up with this:

UCLASS()
class UMySQLRow : public UObject
{
	GENERATED_BODY()

public:
	TMap<FString, FString> rowData;
};

UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Result Data", DataTablePin = "CurveTable"), Category = Database)
	static void getResultData(UMySQLRow* row, FString colName, FString &data);

however the engine crashes when I try to run the game(without running the function at all), I think having UObject as parent class is the problem, but I am not sure how to proceed here, any tips would be great.

In your first example the Problem was the TMap parameter. Blueprints are currently unable to do anything with them. So you cant have sit it there in a UFUNCTION. Your Output Log when you compile should tell you that.

Your Example in your Comment works fine I just run the Code and Started the Game. No Crashes. I assume you have the UFUNCTION inside the class body and not outside like in your Comment and also created a implementation even if its empty? But you are on the right path looks like something else causing the Crash. I mean I can even Construct the Object and Call the Function even if does nothing right now.

Thanks for the answer! It works great now, the only problem is if the key isn’t found I get a fatal error from the engine, so I guess all is left is to make a check. I have this right now:

MySQL.h:

UCLASS(BlueprintType)
class UMySQLRow : public UObject
{
	GENERATED_BODY()

public:
	TMap<FString, FString> rowData;
};


UCLASS()
class DRAGGAMENEW_API UMySQL : public UBlueprintFunctionLibrary
{
	GENERATED_BODY()

	UFUNCTION(BlueprintPure, meta = (DisplayName = "Get Result Data", DataTablePin = "CurveTable"), Category = Database)
	static void getResultData(UMySQLRow* row, FString colName, FString &data);

};

and MySQL.cpp

void UMySQL::getResultData(UMySQLRow* row, FString colName, FString &data)
{
	data = *row->rowData.Find(colName);
	if (*data == nullptr)
	{
		data = "ERROR";
	}
}

this check doesn’t work properly though. Something else is needed. If you have any more ideas I would love to hear them.

void UMySQL::getResultData(UMySqlRow* row, FString colName, FString &data)
{
if (!row)
{
UE_LOG(LogTemp, Warning, TEXT(“Null Object passed to getResultData”));
data = TEXT(“ERROR”);
return;
}
FString* TheValue = row->rowData.Find(colName);
if (TheValue)
{
// Data Found
data = *TheValue;
}
else
{
data = TEXT(“Colum does not exist”);
}
}

If TArray of TMaps is all what you need, then you can easily do this like so:

Header:

TArray<TMap<FString, FString>> Variable;

And here’s the usage:

Variable.Add(TMap<FString, FString>());
Variable[0].Add("Key 1", "Value 1");
Variable[0].Add("Key 2", "Value 2");
Variable[0].Add("Key 3", "Value 3");
Variable[0].Add("Key 4", "Value 4");

Variable.Add(TMap<FString, FString>());
Variable[1].Add("Key 5", "Value 5");
Variable[1].Add("Key 6", "Value 6");

Keep in mind, that, TMaps aren’t supported by UPROPERTY macros so if you’ll add that, the code won’t compile.

If you want to get data from this variable in blueprint, you can do that using this function:

Header:

UFUNCTION(BlueprintPure, Category = "Default")
bool GetValue(const FString& InKey, FString& OutValue, int InRow = -1);

Implementation:

bool AGameStateMultiplayer::GetValue(const FString& InKey, FString& OutValue, int InRow /*= -1*/)
{
     // -1 means we want to search through every row
     if (InRow == -1)
     {
         // Iterating over every row
         for (auto Map : Variable)
         {
             if (Map.Contains(InKey))
             {
                 OutValue = Map[InKey];
                 return true;
             }
         }
     }
     else
     {
         // If row index is valid
         if (InRow > 0 && Variable.Num() > InRow)
         {
             if (Variable[InRow].Contains(InKey))
             {
                 OutValue = Variable[InRow][InKey];
                 return true;
             }
         }
      }
  
      return false;
 }

Cheers.

Thanks for this, however my problem is that I want to expose the output of this variable into blueprints, I am not sure if its possible that way.

That worked wonderfully. Thank you!

Oh, right. Totally missed that part. :stuck_out_tongue:
I’ve added a function you could use to get data from that variable.

InKey - pretty obvious, a key of which value you want to get

OutValue - the value that was found (will have actual value only if whole function returns true)

InRow - you can either specify in which row you want to search for given value, or you can pass ‘-1’ which will cause that whole array will be searched

Thanks! I will give it a try!