안선생의 개발 블로그

[UE5] 언리얼 Wep API - Json형식으로 파싱하기 본문

언리얼/Wep Api

[UE5] 언리얼 Wep API - Json형식으로 파싱하기

안선생 2024. 8. 5. 15:30

먼저 웹서버에서 스웨거 주소가 필요하다. 
스웨거란 쉽게 말해 API 테스트 하기위한 사이트이다.

 

스웨거에서 로그인을 연결할려고 한다.

위에 보시다시피 RequestBody 필요한 매개변수는 4개 의므로 클라쪽에서도 4개의 매개변수를 받는 함수를 만들어줘야 한다.

Curl쪽을 보면 저렇게 보내면 된다.
Curl이란

다양한 프로토콜을 지원하는 데이터 전송용 Command Line Tool이다.

(HTTP, HTTPS, FTP, SFTP, SMTP 등을 지원한다.)



void UWebAPISubsystem::ReqLoginUser(const FString& Email, const FString& Password)
{
    UE_LOG(LogTemp, Log, TEXT("LoginUser"));

    TSharedRef<IHttpRequest> Request = FHttpModule::Get().CreateRequest(); // FHttpModule를 사용하여 HTTP 요청 객체를 생성합니다.
    Request->SetURL(FString(BASE_URL) + TEXT("/account/login")); // URL 설정
    Request->SetVerb(TEXT("POST")); // 방식을 POST로 설정
    Request->SetHeader(TEXT("Content-Type"), TEXT("application/json")); //HTTP 헤더의 Content-Type을 JSON 형식으로 설정합니다.

    //로그인 요청에 필요한 데이터를 JSON 형식의 문자열로 생성합니다. 이메일, 비밀번호, 플랫폼 번호, 언어 설정이 포함
    const FString JsonData = FString::Printf(TEXT("{\"email\":\"%s\",\"password\":\"%s\"}"), *Email, *Password);

    Request->SetContentAsString(JsonData); //생성한 JSON 데이터를 HTTP 요청의 본문으로 설정합니다.
    Request->OnProcessRequestComplete().BindUObject(this, &UWebAPISubsystem::ResLoginUser); //요청 완료 시 호출될 콜백 함수를 바인딩합니다. ResLoginUser 함수가 요청 완료 시 호출됩니다.
    Request->ProcessRequest(); //HTTP 요청을 처리합니다. 이로써 서버로 로그인 요청이 전송됩니다.
}

 

스웨거에 나와있는 Curl을 똑같이 보내주면 된다고 생각하면 된다.

정확하게 보냈다면 아래와같이 ResponseBody에 값들이 들어온다.


저 값은 Json방식으로 들어오는데 클라에서 변환해서 가져와야 된다.

아까 위에서 바인드한 델리게이트는 아래와 같으니 참고하길 바란다.

/**
 * Delegate called when an Http request completes
 *
 * @param Request original Http request that started things
 * @param Response response received from the server if a successful connection was established
 * @param bConnectedSuccessfully - indicates whether or not the request was able to connect successfully
 */
using FHttpRequestCompleteDelegate = TTSDelegate<void(FHttpRequestPtr /*Request*/, FHttpResponsePtr /*Response*/, bool /*bConnectedSuccessfully*/)>;


그럼 위와같은 매개변수를 갖는 함수를 만들어 줘야한다.

값을 정확하게 만들어서 보냈다면 Response에 값이 담아져서 온다.
언리얼에서 Json을 파싱해서 쓰면된다.

TSharedPtr<FJsonObject> JsonObject;
TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(ResponseData);
if (FJsonSerializer::Deserialize(JsonReader, JsonObject))
{
	bWasSuccessful = JsonObject->GetIntegerField(TEXT("result")) == 1;
}

 

위에 부터 하나하나 설명해 보겠다.

// TSharedPtr<FJsonObject> JsonObject; TSharedPtr<FJsonObject> JsonObject;

JsonObject는 JSON 데이터를 담기 위한 스마트 포인터입니다. FJsonObject는 JSON 객체를 나타내는 클래스입니다.

 
 TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(ResponseData);

JsonReader는 JSON 데이터를 읽기 위한 JSON 리더 객체입니다. TJsonReaderFactory<TCHAR>::Create(ResponseData)를 사용하여 ResponseData에서 JSON 데이터를 읽는 리더 객체를 생성합니다. ResponseData는 서버로부터 받은 JSON 형식의 응답 데이터입니다.

 
// if (FJsonSerializer::Deserialize(JsonReader, JsonObject))

FJsonSerializer::Deserialize 함수를 사용하여 JsonReader로부터 JSON 데이터를 읽어 JsonObject로 디시리얼라이즈(역직렬화)합니다. 이 함수는 JSON 데이터를 성공적으로 파싱하면 true를 반환하고, 그렇지 않으면 false를 반환합니다.



이렇게 파싱을 통하면 JsonObject에 있는 값을  아래와 같이 가져올 수 있다.

bWasSuccessful = JsonObject->GetIntegerField(TEXT("result")) == 1;



responsedata에는 인티저, 배열, 스트링 ,구조체 이렇게 오는데 얻는 방법을 알아보겠다.

먼저 인티저는 위에처럼 파싱한 JsonObject를 GetIntergerFiled 함수로 얻어올 수 있다.

FORCEINLINE int32 GetIntegerField(FStringView FieldName) const
{
    return (int32)GetNumberField(FieldName);
}

함수는 이러하다.

 

String 


마찬가지로 GetStringField로 얻을 수 있다. 

DataObject->GetStringField(TEXT("user_name"));

 

 

구조체(Object)

구조체는 방법은 두가지이다 먼저 구조체에 있는 데이터들을 가공해서 가져와서 하는 아래같은 방식이 있다.

 

const TSharedPtr<FJsonObject> DataObject = JsonObject->GetObjectField(TEXT("data"));

이 방식을 사용하면 구조체에 있는 정보들은 다시 DataObject로 가져와야 한다.
Ex)

gender = DataObject->GetIntegerField(TEXT("gender"));

 

두번째 방식은 FJsonObjectConverter를 사용하여 FJsonObject를 Unreal Engine의 사용자 정의 구조체(해당 구조체)로 변환하는 방식이다

const TSharedPtr<FJsonObject> CustomizingObj =DataObject->GetObjectField(TEXT("FiledName"));
FJsonObjectConverter::JsonObjectToUStruct<FCustomizing>(CustomizingObj.ToSharedRef(), &PlayerData->AppearanceData.customizing);


해석을 하면

  1. CustomizingObj라는 FJsonObject를 공유 참조로 변환합니다.
  2. FJsonObjectConverter::JsonObjectToUStruct 함수를 사용하여 CustomizingObj를 FCustomizing 구조체로 변환합니다.
  3. 변환된 구조체 데이터를 PlayerData 객체의 AppearanceData.customizing에 저장합니다. (참조로 넘기는 이유)

이 과정을 통해 서버에서 받은 JSON 데이터가 Unreal Engine의 구조체로 변환되어 게임 내에서 사용할 수 있게 됩니다.


이방식을 사용할라면 해당 클라코드 구조체 변수명이랑 Web서버에서 주는 변수명이 똑같아야 한다(대소문자는 X)



배열 

배열도 비슷하다. 

const TArray<TSharedPtr<FJsonValue>> Array = DataObject->GetArrayField(TEXT("FiledName"));
for (const TSharedPtr<FJsonValue>& Value : Array)
{
    MyData->AchievementInfo.Add(Value->AsNumber());
}

GetArrayField를 통해서  FJsonObject에서 JSON 배열을 추출하고, 그 배열의 값을 특정 데이터 구조체에 추가하는 과정이다.

Value에는 있으니 원하는 형식으로 As해서 값을 넣어주면 된다.



이렇게 언리얼로 Json으로 파싱하는 방법을 알아보았다.