TSharedPtr< FSurveyPage > FSurveyPage::Create( const TSharedRef< class FEpicSurvey >& InEpicSurvey, const TSharedRef< FJsonObject >& JsonObject )
{
	TSharedPtr< FSurveyPage > Page = MakeShareable( new FSurveyPage( InEpicSurvey ) );
	if( JsonObject->HasTypedField< EJson::Array >( "blocks" ) )
	{
		TArray< TSharedPtr< FJsonValue > > JsonSurveyBlocks = JsonObject->GetArrayField( "blocks" );
		for (int Index = 0; Index < JsonSurveyBlocks.Num(); Index++)
		{
			TSharedPtr< FQuestionBlock > Block = FQuestionBlock::Create( InEpicSurvey, JsonSurveyBlocks[Index]->AsObject().ToSharedRef() );
			if ( Block.IsValid() )
			{
				Page->Blocks.Add( Block.ToSharedRef() );
			}
		}
	}
	return Page;
}
bool FJsonInternationalizationArchiveSerializer::JsonObjToArchive(TSharedRef<FJsonObject> InJsonObj, const FString& ParentNamespace, TSharedRef<FInternationalizationArchive> InArchive, TSharedPtr<const FInternationalizationManifest> InManifest, TSharedPtr<const FInternationalizationArchive> InNativeArchive)
{
	bool bConvertSuccess = true;
	FString AccumulatedNamespace = ParentNamespace;

	if (InJsonObj->HasField(TAG_NAMESPACE))
	{
		if (!(AccumulatedNamespace.IsEmpty()))
		{
			AccumulatedNamespace += NAMESPACE_DELIMITER;
		}
		AccumulatedNamespace += InJsonObj->GetStringField(TAG_NAMESPACE);
	}
	else
	{
		UE_LOG(LogInternationalizationArchiveSerializer, Warning, TEXT("Encountered an object with a missing namespace while converting to Internationalization archive."));
		bConvertSuccess = false;
	}

	// Process all the child objects
	if (bConvertSuccess && InJsonObj->HasField(TAG_CHILDREN))
	{
		const TArray< TSharedPtr<FJsonValue> > ChildrenArray = InJsonObj->GetArrayField(TAG_CHILDREN);

		for (TArray< TSharedPtr< FJsonValue > >::TConstIterator ChildIter(ChildrenArray.CreateConstIterator()); ChildIter; ++ChildIter)
		{
			const TSharedPtr< FJsonValue >  ChildEntry = *ChildIter;
			const TSharedPtr< FJsonObject > ChildJSONObject = ChildEntry->AsObject();

			FString SourceText;
			TSharedPtr< FLocMetadataObject > SourceMetadata;
			if (ChildJSONObject->HasTypedField< EJson::String >(TAG_DEPRECATED_DEFAULTTEXT))
			{
				SourceText = ChildJSONObject->GetStringField(TAG_DEPRECATED_DEFAULTTEXT);
			}
			else if (ChildJSONObject->HasTypedField< EJson::Object >(TAG_SOURCE))
			{
				const TSharedPtr< FJsonObject > SourceJSONObject = ChildJSONObject->GetObjectField(TAG_SOURCE);
				if (SourceJSONObject->HasTypedField< EJson::String >(TAG_SOURCE_TEXT))
				{
					SourceText = SourceJSONObject->GetStringField(TAG_SOURCE_TEXT);

					// Source meta data is mixed in with the source text, we'll process metadata if the source json object has more than one entry
					if (SourceJSONObject->Values.Num() > 1)
					{
						// We load in the entire source object as metadata and just remove the source text.
						FJsonInternationalizationMetaDataSerializer::DeserializeMetadata(SourceJSONObject.ToSharedRef(), SourceMetadata);
						if (SourceMetadata.IsValid())
						{
							SourceMetadata->Values.Remove(TAG_SOURCE_TEXT);
						}
					}
				}
				else
				{
					bConvertSuccess = false;
				}
			}
			else
			{
				bConvertSuccess = false;
			}

			FString TranslationText;
			TSharedPtr< FLocMetadataObject > TranslationMetadata;
			if (ChildJSONObject->HasTypedField< EJson::String >(TAG_DEPRECATED_TRANSLATEDTEXT))
			{
				TranslationText = ChildJSONObject->GetStringField(TAG_DEPRECATED_TRANSLATEDTEXT);
			}
			else if (ChildJSONObject->HasTypedField< EJson::Object >(TAG_TRANSLATION))
			{
				const TSharedPtr< FJsonObject > TranslationJSONObject = ChildJSONObject->GetObjectField(TAG_TRANSLATION);
				if (TranslationJSONObject->HasTypedField< EJson::String >(TAG_TRANSLATION_TEXT))
				{
					TranslationText = TranslationJSONObject->GetStringField(TAG_TRANSLATION_TEXT);

					// Source meta data is mixed in with the source text, we'll process metadata if the source json object has more than one entry
					if (TranslationJSONObject->Values.Num() > 1)
					{
						// We load in the entire source object as metadata and remove the source text
						FJsonInternationalizationMetaDataSerializer::DeserializeMetadata(TranslationJSONObject.ToSharedRef(), TranslationMetadata);
						if (TranslationJSONObject.IsValid())
						{
							TranslationJSONObject->Values.Remove(TAG_TRANSLATION_TEXT);
						}
					}
				}
				else
				{
					bConvertSuccess = false;
				}
			}
			else
			{
				bConvertSuccess = false;
			}

			if (bConvertSuccess)
			{
				FLocItem Source(SourceText);
				Source.MetadataObj = SourceMetadata;

				FLocItem Translation(TranslationText);
				Translation.MetadataObj = TranslationMetadata;

				bool bIsOptional = false;
				if (ChildJSONObject->HasTypedField< EJson::Boolean >(TAG_OPTIONAL))
				{
					bIsOptional = ChildJSONObject->GetBoolField(TAG_OPTIONAL);
				}

				TArray<FString> Keys;
				TSharedPtr< FLocMetadataObject > KeyMetadataNode;
				if (InArchive->GetFormatVersion() < FInternationalizationArchive::EFormatVersion::AddedKeys)
				{
					// We used to store the key meta-data as a top-level value, rather than within a "MetaData" object
					if (ChildJSONObject->HasTypedField< EJson::Object >(TAG_METADATA_KEY))
					{
						const TSharedPtr< FJsonObject > MetaDataKeyJSONObject = ChildJSONObject->GetObjectField(TAG_METADATA_KEY);
						FJsonInternationalizationMetaDataSerializer::DeserializeMetadata(MetaDataKeyJSONObject.ToSharedRef(), KeyMetadataNode);
					}

					if (InManifest.IsValid())
					{
						// We have no key in the archive data, so we must try and infer it from the manifest
						FLocTextHelper::FindKeysForLegacyTranslation(InManifest.ToSharedRef(), InNativeArchive, AccumulatedNamespace, SourceText, KeyMetadataNode, Keys);
					}
				}
				else
				{
					if (ChildJSONObject->HasTypedField< EJson::String >(TAG_KEY))
					{
						Keys.Add(ChildJSONObject->GetStringField(TAG_KEY));
					}

					if (ChildJSONObject->HasTypedField< EJson::Object >(TAG_METADATA))
					{
						const TSharedPtr< FJsonObject > MetaDataJSONObject = ChildJSONObject->GetObjectField(TAG_METADATA);

						if (MetaDataJSONObject->HasTypedField< EJson::Object >(TAG_METADATA_KEY))
						{
							const TSharedPtr< FJsonObject > MetaDataKeyJSONObject = MetaDataJSONObject->GetObjectField(TAG_METADATA_KEY);
							FJsonInternationalizationMetaDataSerializer::DeserializeMetadata(MetaDataKeyJSONObject.ToSharedRef(), KeyMetadataNode);
						}
					}
				}

				for (const FString& Key : Keys)
				{
					const bool bAddSuccessful = InArchive->AddEntry(AccumulatedNamespace, Key, Source, Translation, KeyMetadataNode, bIsOptional);
					if (!bAddSuccessful)
					{
						UE_LOG(LogInternationalizationArchiveSerializer, Warning, TEXT("Could not add JSON entry to the Internationalization archive: Namespace:%s Key:%s DefaultText:%s"), *AccumulatedNamespace, *Key, *SourceText);
					}
				}
			}
		}
	}

	if (bConvertSuccess && InJsonObj->HasField(TAG_SUBNAMESPACES))
	{
		const TArray< TSharedPtr<FJsonValue> > SubnamespaceArray = InJsonObj->GetArrayField(TAG_SUBNAMESPACES);

		for (TArray< TSharedPtr< FJsonValue > >::TConstIterator SubnamespaceIter(SubnamespaceArray.CreateConstIterator()); SubnamespaceIter; ++SubnamespaceIter)
		{
			const TSharedPtr< FJsonValue >  SubnamespaceEntry = *SubnamespaceIter;
			const TSharedPtr< FJsonObject > SubnamespaceJSONObject = SubnamespaceEntry->AsObject();

			if (!JsonObjToArchive(SubnamespaceJSONObject.ToSharedRef(), AccumulatedNamespace, InArchive, InManifest, InNativeArchive))
			{
				bConvertSuccess = false;
				break;
			}
		}
	}

	return bConvertSuccess;
}
Example #3
0
TSharedPtr< FQuestionBlock > FQuestionBlock::Create( const TSharedRef< class FEpicSurvey >& InEpicSurvey, const TSharedRef< FJsonObject >& JsonConfig )
{
	TSharedPtr< FQuestionBlock > Block = MakeShareable( new FQuestionBlock( InEpicSurvey ) );

	Block->Style = Style_Inline;
	if ( JsonConfig->HasTypedField< EJson::String >( TEXT("style") ) )
	{
		const FString Style = JsonConfig->GetStringField( TEXT("style") );
		if ( Style == TEXT("multiline")  )
		{
			Block->Style = Style_Multiline;
		}
		else if ( Style == TEXT("multiline-text") )
		{
			Block->Style = Style_MultilineText;
		}
		else if ( Style == TEXT("inline-text") )
		{
			Block->Style = Style_InlineText;
		}
		else if ( Style == TEXT("columns") )
		{
			Block->Style = Style_Columns;
		}
	}

	Block->Instructions = FText::GetEmpty();
	if ( JsonConfig->HasTypedField< EJson::String >( TEXT("instructions") ) )
	{
		Block->Instructions = FText::FromString( JsonConfig->GetStringField( TEXT("instructions") ) );
	}

	Block->bIsRequired = true;
	if ( JsonConfig->HasTypedField< EJson::Boolean >( TEXT("required") ) )
	{
		Block->bIsRequired = JsonConfig->GetBoolField( TEXT("required") );
	}

	Block->Response = FQuestionBlock::Response_Single;
	if ( JsonConfig->HasTypedField< EJson::String >( TEXT("response") ) )
	{
		const FString ResponseString = JsonConfig->GetStringField( TEXT("response") );
		if ( ResponseString == TEXT("multi") )
		{
			Block->Response = FQuestionBlock::Response_Multi;
		}
	}
	else if ( JsonConfig->HasTypedField< EJson::Number >( TEXT("response") ) )
	{
		int32 ResponseNumber = (int32)( JsonConfig->GetNumberField( TEXT("response") ) );
		if ( ResponseNumber <= 0 )
		{
			Block->Response = FQuestionBlock::Response_Multi;
		}
		else if ( ResponseNumber == 1 )
		{
			Block->Response = FQuestionBlock::Response_Multi;
		}
		else
		{
			Block->Response = (FQuestionBlock::EResponse)ResponseNumber;
		}
	}

	if ( JsonConfig->HasTypedField< EJson::Array >( TEXT("questions") ) )
	{
		TArray< TSharedPtr< FJsonValue > > QuestionStrings = JsonConfig->GetArrayField( TEXT("questions") );
		for (int Index = 0; Index < QuestionStrings.Num(); Index++)
		{
			const FString Question = QuestionStrings[Index]->AsString();
			if ( !Question.IsEmpty() )
			{
				Block->Questions.Add( FText::FromString( Question ) );
				Block->UserAnswers.Add( TArray< int32 >() );
				Block->UserTextAnswers.Add( TArray< FString >() );
			}
		}
	}

	if ( JsonConfig->HasTypedField< EJson::Array >( TEXT("answers") ) )
	{
		TArray< TSharedPtr< FJsonValue > > AnswerStrings = JsonConfig->GetArrayField( TEXT("answers") );
		for (int AnswerIndex = 0; AnswerIndex < AnswerStrings.Num(); AnswerIndex++)
		{
			for (int QuestionIndex = 0; QuestionIndex < Block->UserTextAnswers.Num(); QuestionIndex++)
			{
				Block->UserTextAnswers[QuestionIndex].Push( FString() );
			}

			FAnswer Answer;
			switch( AnswerStrings[AnswerIndex]->Type  )
			{
			case EJson::String:
				{
					Answer.Text = FText::FromString( AnswerStrings[AnswerIndex]->AsString() );
				}
				break;
			case EJson::Object:
				{
					TSharedPtr<FJsonObject> SubObject = AnswerStrings[AnswerIndex]->AsObject();
					if( SubObject.IsValid() )
					{
						if( SubObject->HasTypedField< EJson::String >( TEXT("text") ) )
						{
							Answer.Text = FText::FromString( SubObject->GetStringField( TEXT("text") ) );
						}
						if( SubObject->HasTypedField< EJson::Array >( TEXT("branch_points") ) )
						{
							TArray< TSharedPtr< FJsonValue > > BranchPointsArray = SubObject->GetArrayField( TEXT("branch_points") );
							for (int BranchIndex = 0; BranchIndex < BranchPointsArray.Num(); ++BranchIndex)
							{
								TSharedPtr<FJsonObject> BranchObject = BranchPointsArray[BranchIndex]->AsObject();

								if( BranchObject.IsValid() )
								{
									FString BranchName;
									int32 BranchPoints = 0;
									if( BranchObject->HasTypedField< EJson::String >("branch") )
									{
										BranchName = BranchObject->GetStringField("branch");
									}
									if( BranchObject->HasTypedField< EJson::Number >("points") )
									{
										BranchPoints = int32(BranchObject->GetNumberField("points"));
									}
									if( !BranchName.IsEmpty() && (BranchPoints > 0) )
									{
										Answer.Branches.Add( BranchName, BranchPoints );
									}
								}
							}
						}
					}
				}
				break;
			}

			Block->Answers.Add( Answer );
		}
	}

	return Block;
}
Example #4
0
TSharedPtr< FSurvey > FSurvey::Create( const TSharedRef< class FEpicSurvey >& InEpicSurvey, const TSharedRef< FJsonObject >& JsonConfig )
{
	FGuid Identifier;
	if (!FGuid::ParseExact(JsonConfig->GetStringField( TEXT("id") ), EGuidFormats::DigitsWithHyphens, Identifier))
	{
		return nullptr;
	}

	TSharedPtr< FSurvey > NewSurvey( new FSurvey( InEpicSurvey ) );

	NewSurvey->Identifier = Identifier;
	NewSurvey->BannerBrushPath = JsonConfig->GetStringField( TEXT("banner") );
	NewSurvey->DisplayName = FText::FromString( JsonConfig->GetStringField( TEXT("name") ) );
	NewSurvey->Instructions = FText::FromString( JsonConfig->GetStringField( TEXT("instructions") ) );
	NewSurvey->SurveyType = ESurveyType::Normal;
	NewSurvey->AutoPrompt = true;
	NewSurvey->SurveyVersion = 1;
	NewSurvey->MinEngineVersion.Empty();
	NewSurvey->MaxEngineVersion.Empty();
	if ( JsonConfig->HasTypedField<EJson::Boolean>( TEXT("auto_prompt") ) )
	{
		NewSurvey->AutoPrompt = int32(JsonConfig->GetBoolField( TEXT("auto_prompt") ) );
	}
	if( JsonConfig->HasTypedField<EJson::Number>( TEXT("survey_version") ) )
	{
		NewSurvey->SurveyVersion = int32(JsonConfig->GetNumberField( TEXT("survey_version") ) );
	}
	if( JsonConfig->HasTypedField<EJson::String>( TEXT("min_engine_version") ) )
	{
		FEngineVersion::Parse( JsonConfig->GetStringField( TEXT("min_engine_version") ), NewSurvey->MinEngineVersion );
	}
	if (JsonConfig->HasTypedField<EJson::String>(TEXT("max_engine_version")))
	{
		FEngineVersion::Parse( JsonConfig->GetStringField( TEXT("max_engine_version") ), NewSurvey->MaxEngineVersion );
	}
	if( (NewSurvey->SurveyVersion != CurrentSurveyVersion) 
		|| (!NewSurvey->MinEngineVersion.IsEmpty() && GEngineVersion.IsCompatibleWith(NewSurvey->MinEngineVersion))
		|| (!NewSurvey->MaxEngineVersion.IsEmpty() && NewSurvey->MaxEngineVersion.IsCompatibleWith(GEngineVersion)) )
	{
		return NULL;
	}

	if( JsonConfig->HasTypedField<EJson::String>( "type" ) )
	{
		FString SurveyType = JsonConfig->GetStringField( TEXT("type") );
		if( !SurveyType.IsEmpty() )
		{
			if( SurveyType == TEXT( "branch" ) )
			{
				NewSurvey->SurveyType = ESurveyType::Branch;
			}
		}
	}

	if( JsonConfig->HasTypedField< EJson::Array >( "branches" ) )
	{
		TArray< TSharedPtr< FJsonValue > > JsonSurveyBranches = JsonConfig->GetArrayField( "branches" );
		for (int Index = 0; Index < JsonSurveyBranches.Num(); Index++)
		{
			TSharedPtr< FSurveyBranch > Branch = FSurveyBranch::Create( InEpicSurvey, JsonSurveyBranches[Index]->AsObject().ToSharedRef() );
			if ( Branch.IsValid() )
			{
				NewSurvey->Branches.Add( Branch.ToSharedRef() );
				InEpicSurvey->AddBranch( Branch->GetBranchName() );
			}
		}
	}

	if( JsonConfig->HasTypedField< EJson::Array >( "pages" ) )
	{
		TArray< TSharedPtr< FJsonValue > > JsonSurveyPages = JsonConfig->GetArrayField( "pages" );
		for (int Index = 0; Index < JsonSurveyPages.Num(); Index++)
		{
			TSharedPtr< FJsonObject > PageObject = JsonSurveyPages[Index]->AsObject();
			
			if( PageObject.IsValid() )
			{
				TSharedPtr<FSurveyPage> Page = FSurveyPage::Create( InEpicSurvey, PageObject.ToSharedRef() );

				if( Page.IsValid() )
				{
					NewSurvey->Pages.Add( Page.ToSharedRef() );

					if( NewSurvey->SurveyType == ESurveyType::Branch )
					{
						Page->SetBranchSurvey( NewSurvey );
					}
				}
			}
		}
	}
	else
	{
		TSharedPtr<FSurveyPage> Page = FSurveyPage::Create( InEpicSurvey, JsonConfig );

		if( Page.IsValid() )
		{
			NewSurvey->Pages.Add( Page.ToSharedRef() );
		}
	}

	return NewSurvey;
}
bool FInternationalizationManifestJsonSerializer::JsonObjToManifest( TSharedRef< FJsonObject > InJsonObj, FString ParentNamespace, TSharedRef< FInternationalizationManifest > Manifest )
{
	bool bConvertSuccess = true;
	FString AccumulatedNamespace = ParentNamespace;
	if( InJsonObj->HasField( TAG_NAMESPACE) )
	{
		if( !( AccumulatedNamespace.IsEmpty() ) )
		{
			AccumulatedNamespace += NAMESPACE_DELIMITER;
		}
		AccumulatedNamespace += InJsonObj->GetStringField( TAG_NAMESPACE );
	}
	else
	{
		// We found an entry with a missing namespace
		bConvertSuccess = false;
	}

	// Process all the child objects
	if( bConvertSuccess && InJsonObj->HasField( TAG_CHILDREN ) )
	{
		const TArray< TSharedPtr< FJsonValue> > ChildrenArray = InJsonObj->GetArrayField( TAG_CHILDREN );

		for(TArray< TSharedPtr< FJsonValue > >::TConstIterator ChildIter( ChildrenArray.CreateConstIterator() ); ChildIter && bConvertSuccess; ++ChildIter)
		{
			const TSharedPtr< FJsonValue >  ChildEntry = *ChildIter;
			const TSharedPtr< FJsonObject > ChildJSONObject = ChildEntry->AsObject();

			
			FString SourceText;
			TSharedPtr< FLocMetadataObject > SourceMetadata;
			if( ChildJSONObject->HasTypedField< EJson::String>( TAG_DEPRECATED_DEFAULTTEXT) )
			{
				SourceText = ChildJSONObject->GetStringField( TAG_DEPRECATED_DEFAULTTEXT );
			}
			else if( ChildJSONObject->HasTypedField< EJson::Object>( TAG_SOURCE ) )
			{
				const TSharedPtr< FJsonObject > SourceJSONObject = ChildJSONObject->GetObjectField( TAG_SOURCE );
				if( SourceJSONObject->HasTypedField< EJson::String >( TAG_SOURCE_TEXT ) )
				{
					SourceText = SourceJSONObject->GetStringField( TAG_SOURCE_TEXT );

					// Source meta data is mixed in with the source text, we'll process metadata if the source json object has more than one entry
					if( SourceJSONObject->Values.Num() > 1 )
					{
						// We load in the entire source object as metadata and remove the source object
						FInternationalizationMetaDataJsonSerializer::DeserializeMetadata( SourceJSONObject.ToSharedRef(), SourceMetadata );
						if( SourceMetadata.IsValid() )
						{
							SourceMetadata->Values.Remove( TAG_SOURCE_TEXT );
						}
					}
				}
				else
				{
					bConvertSuccess = false;
				}
			}
			else
			{
				bConvertSuccess = false;
			}

			FLocItem Source(SourceText);
			Source.MetadataObj = SourceMetadata;

			if( bConvertSuccess && ChildJSONObject->HasField( TAG_KEYCOLLECTION ) )
			{
				
				const TArray< TSharedPtr<FJsonValue> > ContextArray = ChildJSONObject->GetArrayField( TAG_KEYCOLLECTION);

				for(TArray< TSharedPtr< FJsonValue > >::TConstIterator ContextIter( ContextArray.CreateConstIterator() ); ContextIter && bConvertSuccess; ++ContextIter)
				{
					const TSharedPtr< FJsonValue > ContextEntry = *ContextIter;
					const TSharedPtr< FJsonObject > ContextJSONObject = ContextEntry->AsObject();

					if( ContextJSONObject->HasTypedField< EJson::String >( TAG_KEY ) )
					{
						const FString Key = ContextJSONObject->GetStringField( TAG_KEY );
						const FString SourceLocation = ContextJSONObject->HasField( TAG_PATH ) ? ContextJSONObject->GetStringField( TAG_PATH ) : FString();

						FContext CommandContext;
						CommandContext.Key = Key;
						CommandContext.SourceLocation = SourceLocation;

						if( ContextJSONObject->HasTypedField< EJson::Boolean >( TAG_OPTIONAL ) )
						{
							CommandContext.bIsOptional = ContextJSONObject->GetBoolField( TAG_OPTIONAL );
						}

						if( ContextJSONObject->HasTypedField< EJson::Object >( TAG_METADATA ) )
						{
							const TSharedPtr< FJsonObject > MetaDataJSONObject = ContextJSONObject->GetObjectField( TAG_METADATA );

							if( MetaDataJSONObject->HasTypedField< EJson::Object >( TAG_METADATA_INFO ) )
							{
								const TSharedPtr< FJsonObject > MetaDataInfoJSONObject = MetaDataJSONObject->GetObjectField( TAG_METADATA_INFO );

								TSharedPtr< FLocMetadataObject > MetadataNode;
								FInternationalizationMetaDataJsonSerializer::DeserializeMetadata( MetaDataInfoJSONObject.ToSharedRef(), MetadataNode );
								if( MetadataNode.IsValid() )
								{
									CommandContext.InfoMetadataObj = MetadataNode;
								}
							}

							if( MetaDataJSONObject->HasTypedField< EJson::Object >( TAG_METADATA_KEY ) )
							{
								const TSharedPtr< FJsonObject > MetaDataKeyJSONObject = MetaDataJSONObject->GetObjectField( TAG_METADATA_KEY );

								TSharedPtr< FLocMetadataObject > MetadataNode;
								FInternationalizationMetaDataJsonSerializer::DeserializeMetadata( MetaDataKeyJSONObject.ToSharedRef(), MetadataNode );
								if( MetadataNode.IsValid() )
								{
									CommandContext.KeyMetadataObj = MetadataNode;
								}
							}
						}
						bool bAddSuccessful = Manifest->AddSource( AccumulatedNamespace, Source, CommandContext );
						if(!bAddSuccessful)
						{
							UE_LOG( LogInternationalizationManifestSerializer, Warning,TEXT("Could not add JSON entry to the Internationalization manifest: Namespace:%s SourceText:%s SourceData:%s"), 
								*AccumulatedNamespace, 
								*SourceText, 
								*FInternationalizationMetaDataJsonSerializer::MetadataToString(Source.MetadataObj) );
						}
					}
					else
					{
						//We found a context entry that is missing a identifier/key or a path
						bConvertSuccess = false;
						break;
					}

				}
			}
			else
			{
				// We have an entry that is missing a key/context collection or default text entry.
				bConvertSuccess = false;
				break;
			}

		}
	}

	if( bConvertSuccess && InJsonObj->HasField( TAG_SUBNAMESPACES ) )
	{
		const TArray< TSharedPtr<FJsonValue> > SubnamespaceArray = InJsonObj->GetArrayField( TAG_SUBNAMESPACES );

		for(TArray< TSharedPtr< FJsonValue > >::TConstIterator SubnamespaceIter( SubnamespaceArray.CreateConstIterator() ); SubnamespaceIter; ++SubnamespaceIter )
		{
			const TSharedPtr< FJsonValue >  SubnamespaceEntry = *SubnamespaceIter;
			const TSharedPtr< FJsonObject > SubnamespaceJSONObject = SubnamespaceEntry->AsObject();

			if( !JsonObjToManifest( SubnamespaceJSONObject.ToSharedRef(), AccumulatedNamespace, Manifest ) )
			{
				bConvertSuccess = false;
				break;
			}
		}
	}
	
	return bConvertSuccess;
}
bool FInternationalizationArchiveJsonSerializer::JsonObjToArchive( TSharedRef< FJsonObject > InJsonObj, FString ParentNamespace, TSharedRef< FInternationalizationArchive > InternationalizationArchive )
{
	bool bConvertSuccess = true;
	FString AccumulatedNamespace = ParentNamespace;
	
	if( InJsonObj->HasField( TAG_NAMESPACE) )
	{
		if( !( AccumulatedNamespace.IsEmpty() ) )
		{
			AccumulatedNamespace += NAMESPACE_DELIMITER;
		}
		AccumulatedNamespace += InJsonObj->GetStringField( TAG_NAMESPACE );
	}
	else
	{
		UE_LOG( LogInternationalizationArchiveSerializer, Warning,TEXT("Encountered an object with a missing namespace while converting to Internationalization archive.") );
		bConvertSuccess = false;
	}

	// Process all the child objects
	if( bConvertSuccess && InJsonObj->HasField( TAG_CHILDREN ) )
	{
		const TArray< TSharedPtr<FJsonValue> > ChildrenArray = InJsonObj->GetArrayField( TAG_CHILDREN );

		for( TArray< TSharedPtr< FJsonValue > >::TConstIterator ChildIter( ChildrenArray.CreateConstIterator() ); ChildIter; ++ChildIter )
		{
			const TSharedPtr< FJsonValue >  ChildEntry = *ChildIter;
			const TSharedPtr< FJsonObject > ChildJSONObject = ChildEntry->AsObject();

			FString SourceText;
			TSharedPtr< FLocMetadataObject > SourceMetadata;
			if( ChildJSONObject->HasTypedField< EJson::String >( TAG_DEPRECATED_DEFAULTTEXT ) )
			{
				SourceText = ChildJSONObject->GetStringField( TAG_DEPRECATED_DEFAULTTEXT );
			} 
			else if( ChildJSONObject->HasTypedField< EJson::Object >( TAG_SOURCE ) )
			{
				const TSharedPtr< FJsonObject > SourceJSONObject = ChildJSONObject->GetObjectField( TAG_SOURCE );
				if( SourceJSONObject->HasTypedField< EJson::String >( TAG_SOURCE_TEXT ) )
				{
					SourceText = SourceJSONObject->GetStringField( TAG_SOURCE_TEXT );

					// Source meta data is mixed in with the source text, we'll process metadata if the source json object has more than one entry
					if( SourceJSONObject->Values.Num() > 1 )
					{
						// We load in the entire source object as metadata and just remove the source text.
						FInternationalizationMetaDataJsonSerializer::DeserializeMetadata( SourceJSONObject.ToSharedRef(), SourceMetadata );
						if( SourceMetadata.IsValid() )
						{
							SourceMetadata->Values.Remove( TAG_SOURCE_TEXT );
						}
					}
				}
				else
				{
					bConvertSuccess = false;
				}
			}
			else
			{
				bConvertSuccess = false;
			}

			FString TranslationText;
			TSharedPtr< FLocMetadataObject > TranslationMetadata;
			if( ChildJSONObject->HasTypedField< EJson::String >( TAG_DEPRECATED_TRANSLATEDTEXT ) )
			{
				TranslationText = ChildJSONObject->GetStringField( TAG_DEPRECATED_TRANSLATEDTEXT );
			} 
			else if( ChildJSONObject->HasTypedField< EJson::Object >( TAG_TRANSLATION ) )
			{
				const TSharedPtr< FJsonObject > TranslationJSONObject = ChildJSONObject->GetObjectField( TAG_TRANSLATION );
				if( TranslationJSONObject->HasTypedField< EJson::String >( TAG_TRANSLATION_TEXT ) )
				{
					TranslationText = TranslationJSONObject->GetStringField( TAG_TRANSLATION_TEXT );

					// Source meta data is mixed in with the source text, we'll process metadata if the source json object has more than one entry
					if( TranslationJSONObject->Values.Num() > 1 )
					{
						// We load in the entire source object as metadata and remove the source text
						FInternationalizationMetaDataJsonSerializer::DeserializeMetadata( TranslationJSONObject.ToSharedRef(), TranslationMetadata );
						if( TranslationJSONObject.IsValid() )
						{
							TranslationJSONObject->Values.Remove( TAG_TRANSLATION_TEXT );
						}
					}
				}
				else
				{
					bConvertSuccess = false;
				}
			}
			else
			{
				bConvertSuccess = false;
			}

			if( bConvertSuccess )
			{
				FLocItem Source( SourceText );
				Source.MetadataObj = SourceMetadata;

				FLocItem Translation( TranslationText );
				Translation.MetadataObj = TranslationMetadata;

				bool bIsOptional = false;
				if( ChildJSONObject->HasTypedField< EJson::Boolean >( TAG_OPTIONAL ) )
				{
					bIsOptional = ChildJSONObject->GetBoolField( TAG_OPTIONAL );
				}

				TSharedPtr< FLocMetadataObject > MetadataNode;
				if( ChildJSONObject->HasTypedField< EJson::Object >( TAG_METADATA_KEY ) )
				{
					const TSharedPtr< FJsonObject > MetaDataKeyJSONObject = ChildJSONObject->GetObjectField( TAG_METADATA_KEY );
					FInternationalizationMetaDataJsonSerializer::DeserializeMetadata( MetaDataKeyJSONObject.ToSharedRef(), MetadataNode );
				}

				bool bAddSuccessful = InternationalizationArchive->AddEntry( AccumulatedNamespace, Source, Translation, MetadataNode, bIsOptional );
				if( !bAddSuccessful )
				{
					UE_LOG( LogInternationalizationArchiveSerializer, Warning,TEXT("Could not add JSON entry to the Internationalization archive: Namespace:%s DefaultText:%s"), *AccumulatedNamespace, *SourceText );
				}
			}
		}
	}

	if( bConvertSuccess && InJsonObj->HasField( TAG_SUBNAMESPACES ) )
	{
		const TArray< TSharedPtr<FJsonValue> > SubnamespaceArray = InJsonObj->GetArrayField( TAG_SUBNAMESPACES );

		for(TArray< TSharedPtr< FJsonValue > >::TConstIterator SubnamespaceIter( SubnamespaceArray.CreateConstIterator() ); SubnamespaceIter; ++SubnamespaceIter )
		{
			const TSharedPtr< FJsonValue >  SubnamespaceEntry = *SubnamespaceIter;
			const TSharedPtr< FJsonObject > SubnamespaceJSONObject = SubnamespaceEntry->AsObject();

			if( !JsonObjToArchive( SubnamespaceJSONObject.ToSharedRef(), AccumulatedNamespace, InternationalizationArchive ) )
			{
				bConvertSuccess = false;
				break;
			}
		}
	}

	return bConvertSuccess;
}