bool FDataTableImporterJSON::ReadRow(const TSharedRef<FJsonObject>& ParsedTableRowObject, const int32 RowIdx) { // Get row name FName RowName = DataTableUtils::MakeValidName(ParsedTableRowObject->GetStringField(TEXT("Name"))); // Check its not 'none' if (RowName.IsNone()) { ImportProblems.Add(FString::Printf(TEXT("Row '%d' missing a name."), RowIdx)); return false; } // Check its not a duplicate if (DataTable->RowMap.Find(RowName) != nullptr) { ImportProblems.Add(FString::Printf(TEXT("Duplicate row name '%s'."), *RowName.ToString())); return false; } // Allocate data to store information, using UScriptStruct to know its size uint8* RowData = (uint8*)FMemory::Malloc(DataTable->RowStruct->PropertiesSize); DataTable->RowStruct->InitializeStruct(RowData); // And be sure to call DestroyScriptStruct later if (auto UDStruct = Cast<const UUserDefinedStruct>(DataTable->RowStruct)) { UDStruct->InitializeDefaultValue(RowData); } // Add to row map DataTable->RowMap.Add(RowName, RowData); // Now read in each property for (TFieldIterator<UProperty> It(DataTable->RowStruct); It; ++It) { UProperty* BaseProp = *It; check(BaseProp); const FString PropertyName = BaseProp->GetName(); TSharedPtr<FJsonValue> ParsedPropertyValue = ParsedTableRowObject->TryGetField(PropertyName); if (!ParsedPropertyValue.IsValid()) { ImportProblems.Add(FString::Printf(TEXT("Row '%s' is missing an entry for '%s'."), *RowName.ToString(), *PropertyName)); continue; } void* Data = BaseProp->ContainerPtrToValuePtr<void>(RowData, 0); ReadStructEntry(ParsedPropertyValue.ToSharedRef(), RowName, RowData, BaseProp, Data); } return true; }
bool FDataTableImporterJSON::ReadStruct(const TSharedRef<FJsonObject>& InParsedObject, UScriptStruct* InStruct, const FName InRowName, void* InStructData) { // Now read in each property for (TFieldIterator<UProperty> It(InStruct); It; ++It) { UProperty* BaseProp = *It; check(BaseProp); const FString ColumnName = DataTableUtils::GetPropertyDisplayName(BaseProp, BaseProp->GetName()); TSharedPtr<FJsonValue> ParsedPropertyValue; for (const FString& PropertyName : DataTableUtils::GetPropertyImportNames(BaseProp)) { ParsedPropertyValue = InParsedObject->TryGetField(PropertyName); if (ParsedPropertyValue.IsValid()) { break; } } if (!ParsedPropertyValue.IsValid()) { ImportProblems.Add(FString::Printf(TEXT("Row '%s' is missing an entry for '%s'."), *InRowName.ToString(), *ColumnName)); continue; } if (BaseProp->ArrayDim == 1) { void* Data = BaseProp->ContainerPtrToValuePtr<void>(InStructData, 0); ReadStructEntry(ParsedPropertyValue.ToSharedRef(), InRowName, ColumnName, InStructData, BaseProp, Data); } else { const TCHAR* const ParsedPropertyType = JSONTypeToString(ParsedPropertyValue->Type); const TArray< TSharedPtr<FJsonValue> >* PropertyValuesPtr; if (!ParsedPropertyValue->TryGetArray(PropertyValuesPtr)) { ImportProblems.Add(FString::Printf(TEXT("Property '%s' on row '%s' is the incorrect type. Expected Array, got %s."), *ColumnName, *InRowName.ToString(), ParsedPropertyType)); return false; } if (BaseProp->ArrayDim != PropertyValuesPtr->Num()) { ImportProblems.Add(FString::Printf(TEXT("Property '%s' on row '%s' is a static sized array with %d elements, but we have %d values to import"), *ColumnName, *InRowName.ToString(), BaseProp->ArrayDim, PropertyValuesPtr->Num())); } for (int32 ArrayEntryIndex = 0; ArrayEntryIndex < BaseProp->ArrayDim; ++ArrayEntryIndex) { if (PropertyValuesPtr->IsValidIndex(ArrayEntryIndex)) { void* Data = BaseProp->ContainerPtrToValuePtr<void>(InStructData, ArrayEntryIndex); const TSharedPtr<FJsonValue>& PropertyValueEntry = (*PropertyValuesPtr)[ArrayEntryIndex]; ReadArrayEntry(PropertyValueEntry.ToSharedRef(), InRowName, ColumnName, ArrayEntryIndex, BaseProp, Data); } } } } return true; }