Server/NodeJS & NestJS

NestJS) JSON.stringify Object DTO에서 확인하기

Juzdalua 2022. 7. 8. 17:48

FE에서 이미지를 전송할 때, body가 아닌 FormData로 전송해야 BE에서 데이터를 받을 수 있다.

FormData로 데이터를 전송할 때에는 JSON타입 Object, Array를 담을 수 없다.

FormData는 밸류값을 string | blob만 처리하기 때문.

form.append("data", [1,2]);

 

그래서 리스트형식 데이터는 JSON.stringify(data)로 문자화 시켜서 전송해야한다.

// FE

const body = {
  stringValue: sValue as string,
  listValue: lValue as Array<any>
};

let form = new FormData();
for(const key of Object.entries(body)){
  if(typeof key[1] === 'object'){
    form.append(key[0],JSON.stringify(key[1]));
  } else{
    form.append(key[0],key[1]);
  }
}

const result = await axios.post(URL, form);

 

BE에서 NestJS DTO로 Body를 체크할 때 문제가 발생한다.

@IsString으로 체크하면 통과되지만, 해당 값을 파싱했을 때 결과값을 신뢰할 수 없다.

@IsJson으로 체크하면 통과되지만, 해당 값은 파싱이 불가능하다.

 

배열 리스트로 전송했다면 파싱된 값이 배열인지 확인해야했다.

class-transformer 라이브러리를 활용해서 이를 해결했다.

 

// BE

import { Transform } from "class-transformer";
import { IsArray, IsString } from "class-validator";

interface listItem{
  title: string,
  description: string,
  tags: string[]
}

export class JsonParseDTO{
  @IsString()
  readonly sValue: string;

  @IsArray()
  @Transform(property => JSON.parse(property.value))
  readonly lValue: Array<listItem>;
}

@Transform에서 lValue 프로퍼티를 파싱하고 파싱된 값이 배열인지 확인하는 DTO다.

배열이 아닌 Object 리스트라면 @IsObject() 데코레이터를 사용하면 된다.

 

리스트가 아닌 Date형식이라면 다음과 같이 사용하면 된다.

@IsDate()
@Type(()=>Date)
readonly dValue: Date = null;