#NestJS + Multer: Nested JSON Arrays Not Parsing in Multipart Form Data

8 messages · Page 1 of 1 (latest)

inland flume
#

Hi NestJS community!

I'm struggling with handling a multipart/form-data request that contains both files and a nested JSON object with arrays. My Flutter client is sending the data correctly, but the JSON arrays aren't being properly parsed on the NestJS side despite using class-transformer.

My setup:

  • Frontend: Flutter using dio package
  • Backend: NestJS with @nestjs/platform-express, multer, and class-transformer
  • Endpoint: POST /api/upload

What I'm trying to do:
Send a request that contains:

  1. File(s)
  2. A JSON field that contains an array of objects

Flutter code:

FormData formData = FormData.fromMap({
  'file': await MultipartFile.fromFile('path/to/file.pdf'),
  'json': jsonEncode({
    'user': {
      'name': 'John',
      'items': [
        { 'id': 1, 'name': 'Item 1' },
        { 'id': 2, 'name': 'Item 2' }
      ]
    }
  })
});

await dio.post('http://my-api/upload', data: formData);
#

My DTOs:

class ItemDto {
  @IsNumber()
  id: number;
  
  @IsString()
  name: string;
}

class UserDto {
  @IsString()
  name: string;
  
  @IsArray()
  @ValidateNested({ each: true })
  @Type(() => ItemDto)
  items: ItemDto[];
}

class UploadDto {
  @ValidateNested()
  @Type(() => UserDto)
  user: UserDto;
}

NestJS controller with multer:

@Post('upload')
@UseInterceptors(FileInterceptor('file', {
  storage: diskStorage({
    destination: './uploads',
    filename: (req, file, cb) => {
      const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
      cb(null, `file-${uniqueSuffix}${extname(file.originalname)}`);
    },
  }),
}))
async uploadFile(
  @UploadedFile() file: Express.Multer.File,
  @Body() body: any
) {
  console.log('File:', file.filename);
  console.log('Body:', body);
  
  try {
    // Parse the JSON string
    const jsonData = JSON.parse(body.json);
    console.log('Parsed raw:', jsonData);
    
    // Try to transform using class-transformer
    const dto = plainToClass(UploadDto, jsonData);
    console.log('Transformed:', dto);
    
    // This is where the issue happens - items array is empty or undefined
    console.log('Items:', dto.user.items);
    
    return { success: true };
  } catch (error) {
    console.error('Error:', error);
    throw new BadRequestException('Invalid data format');
  }
}

The issue:
When I log dto.user.items, it's either undefined, empty, or not recognized as a proper array of objects despite using class-transformer
decorators. The nested array structure seems to get lost in the transformation process.
What I've tried:

Using JSON.parse() on the body.json string first
Using class-transformerdecorators at every level
Different Content-Type headers in the Flutter client
Adding transformOptions to plainToClass: plainToClass(UploadDto, jsonData, { enableImplicitConversion: true })

#

Has anyone successfully handled complex nested arrays within JSON data in multipart/form-data requests with NestJS using Multer and class-transformer? I feel like I'm missing something fundamental about how these libraries interact with multipart data.
Thank you in advance!

bright socket
#

i have the same problem

terse summit
#

Multer only natively supports strings in the body. It doesn't JSON decode anything. So when class-transformer gets the parsed body from multer, your items property contains a json-encoded string, not a parsed object.

#

What could help is if you add a @Transform(({ value }) => JSON.parse(value)) on top of that property

bright socket
terse summit
#

Well, the multipart/form-data format itself doesn't natively support nested structures. It only supports key/value pairs, where the value can either be a string or a binary representation of a file.

You can also send the file as a base64-encoded string within a JSON, which would allow you to have nested structures out of the box, but it's inefficient