Unresolved External Symbol with TArray of structs

Error:

1>XmlReader.cpp.obj : error LNK2019: unresolved external symbol "public: class TArray<struct FSBuilding,class FDefaultAllocator> __cdecl UXmlReader::LoadBuildings(class ULowEntryXmlParserNode *)" (?LoadBuildings@UXmlReader@@QEAA?AV?$TArray@UFSBuilding@@VFDefaultAllocator@@@@PEAVULowEntryXmlParserNode@@@Z) referenced in function "public: static void __cdecl UXmlReader::execLoadBuildings(class UObject *,struct FFrame &,void * const)" (?execLoadBuildings@UXmlReader@@SAXPEAVUObject@@AEAUFFrame@@QEAX@Z)
1>XmlReader.gen.cpp.obj : error LNK2001: unresolved external symbol "public: class TArray<struct FSBuilding,class FDefaultAllocator> __cdecl UXmlReader::LoadBuildings(class ULowEntryXmlParserNode *)" (?LoadBuildings@UXmlReader@@QEAA?AV?$TArray@UFSBuilding@@VFDefaultAllocator@@@@PEAVULowEntryXmlParserNode@@@Z)

Header:

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "XmlReader.generated.h"

class ULowEntryXmlParserNode;

USTRUCT(BlueprintType)
struct FSResource
{
	GENERATED_BODY()

public:

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		FString Resource;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		int32 Amount;

	FSResource(){}
};

USTRUCT(BlueprintType)
struct FSBuilding
{
	GENERATED_BODY()

public:

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		int32 ID;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		FString Name;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		FString Icon;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		FString Mesh;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		FString Category;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		int32 SizeX;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		int32 SizeY;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		TMap<FString, bool> Flags;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		int32 Hitpoints;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		TArray<FSResource> Cost;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		TArray<FString> AllowedTerrains;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		TArray<FString> RequiredTerrains;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		TArray<FString> AllowedResources;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		TArray<FString> Units;

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Buildings")
		TArray<FString> Techs;

	FSBuilding()
	{

	}
};

UCLASS()
class CITY_API UXmlReader : public UObject
{
	GENERATED_BODY()

	public:
	UFUNCTION(BlueprintCallable)
		TArray<FSBuilding> LoadBuildings(ULowEntryXmlParserNode* Node);
};

CPP:

// Fill out your copyright notice in the Description page of Project Settings.

#include "XmlReader.h"
#include "LowEntryXmlParserNode.h"

TArray<FSBuilding> LoadBuildings(ULowEntryXmlParserNode* Node)
{
	TArray<ULowEntryXmlParserNode*> Buildings = Node->GetChildrenNodes();
	TArray<FSBuilding> DataArray;

	for (ULowEntryXmlParserNode* Building : Buildings)
	{
		FSBuilding Data = FSBuilding();
		Data.ID = FCString::Atoi(*Building->GetAttribute("id"));

		TArray<ULowEntryXmlParserNode*> BuildingSubnodes = Building->GetChildrenNodes();

		for (ULowEntryXmlParserNode* BuildingSubnode : BuildingSubnodes)
		{
			if (BuildingSubnode->GetTag() == "name")
			{
				Data.Name = BuildingSubnode->GetValue();
				continue;
			}

			if (BuildingSubnode->GetTag() == "icon")
			{
				Data.Icon = BuildingSubnode->GetValue();
				continue;
			}

			if (BuildingSubnode->GetTag() == "mesh")
			{
				Data.Mesh = BuildingSubnode->GetValue();
				continue;
			}

			if (BuildingSubnode->GetTag() == "category")
			{
				Data.Category = BuildingSubnode->GetValue();
				continue;
			}

			if (BuildingSubnode->GetTag() == "sizeY")
			{
				Data.SizeX = FCString::Atoi(*BuildingSubnode->GetValue());
				continue;
			}
			
			if (BuildingSubnode->GetTag() == "sizeX")
			{
				Data.SizeY = FCString::Atoi(*BuildingSubnode->GetValue());
				continue;
			}

			if (BuildingSubnode->GetTag() == "hitpoints")
			{
				Data.Hitpoints = FCString::Atoi(*BuildingSubnode->GetValue());
				continue;
			}

			if (BuildingSubnode->GetTag() == "flags")
			{
				TArray<ULowEntryXmlParserNode*> Flags = BuildingSubnode->GetChildrenNodes();

				for (ULowEntryXmlParserNode* Flag : Flags)
				{
					FString Name = Flag->GetAttribute("name");
					bool Value = FCString::ToBool(*Flag->GetValue());

					Data.Flags.Add(Name, Value);
				}
				continue;
			}

			if (BuildingSubnode->GetTag() == "cost")
			{
				TArray<ULowEntryXmlParserNode*> CostNodes = BuildingSubnode->GetChildrenNodes();

				for (ULowEntryXmlParserNode* CostNode : CostNodes)
				{
					FSResource Resource = FSResource();
					Resource.Resource = CostNode->GetAttribute("type");
					Resource.Amount = FCString::Atoi(*CostNode->GetValue());

					Data.Cost.Add(Resource);
				}
			}

			if (BuildingSubnode->GetTag() == "allowedTerrains")
			{
				TArray<ULowEntryXmlParserNode*> TerrainNodes = BuildingSubnode->GetChildrenNodes();

				for (ULowEntryXmlParserNode* Terrain : TerrainNodes)
				{
					Data.AllowedTerrains.Add(Terrain->GetValue());
				}
				continue;
			}

			if (BuildingSubnode->GetTag() == "allowedResources")
			{
				TArray<ULowEntryXmlParserNode*> Allowed = BuildingSubnode->GetChildrenNodes();

				for (ULowEntryXmlParserNode* Allow : Allowed)
				{
					Data.AllowedResources.Add(Allow->GetValue());
				}
				continue;
			}
		}
		DataArray.Add(Data);
	}
	return DataArray;
}

Seems like the issue was a misunderstanding on my part. I changed GENERATED_USTRUCT_BODY() in the struct to GENERATED_BODY() and it compiled properly. I think the former requires you to add a constructor that initializes default values for the structs values.