Validering av nästlade och arraybaserade DTO:er
Validera nästlade objekt och samlingar med @ValidateNested, @Type och borttagning via whitelist.
Validering av nästlade och arraybaserade DTO:er är en gratis lektion i NestJS: backend-API:er för företag på CoddyKit. Detta är lektion 1 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för NestJS: backend-API:er för företag, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i NestJS: backend-API:er för företag innehåller totalt 4 lektioner.
Varför nästlad validering behöver hjälp
NestJS kopplar samman class-validator och class-transformer via den globala ValidationPipe. För platta DTO:er fungerar detta direkt: dekoratorerna på varje egenskap körs automatiskt.
Men så fort en DTO innehåller ett annat objekt eller en array med objekt upphör valideringen tyst vid gränsen. Validatorn ser en underordnad egenskap, men vet inte att den är en klassinstans vars egna dekoratorer ska köras.
- Ett nästlat
address-objekt behandlas som ett ogenomskinligt värde. - En
items-array kontrolleras för att se om den är en array, men elementen valideras aldrig.
I den här lektionen visar vi hur @ValidateNested, @Type och borttagning med whitelist täpper igen dessa luckor.
Problemet i koden
Anta att en order-payload innehåller en nästlad address. Att enbart lägga till @ValidateNested är inte tillräckligt — validatorn behöver fortfarande att det underordnade objektet faktiskt är en instans av AddressDto, inte ett vanligt objekt.
Utan @Type lämnar class-transformer address som ett vanligt objekt, så @IsString() på city körs aldrig. Ogiltiga data släpps igenom obemärkt.
import { IsString, ValidateNested } from 'class-validator';
// AddressDto's own rules will NOT run yet
class AddressDto {
@IsString()
city: string;
}
export class CreateOrderDto {
@ValidateNested() // declares intent, but lacks a target type
address: AddressDto;
}@Type gör det underordnade objektet till en riktig instans
Det som saknas är @Type(() => AddressDto) från class-transformer. Den talar om för transformeraren hur det nästlade värdet ska konstrueras och omvandlar det råa JSON-objektet till en riktig instans av AddressDto.
Först då körs det underordnade objektets dekoratorer (@IsString, @IsNotEmpty osv.) faktiskt. Tumregeln är:
- @ValidateNested() → ”gå rekursivt igenom den här egenskapen”.
- @Type(() => Child) → ”bygg den först som den här klassen”.
Ni behöver nästan alltid båda tillsammans.
import { IsString, IsPostalCode, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
class AddressDto {
@IsString()
city: string;
@IsPostalCode('US')
zip: string;
}
export class CreateOrderDto {
@ValidateNested()
@Type(() => AddressDto)
address: AddressDto;
}Aktivera transform i pipen
För att @Type ska få effekt måste ValidationPipe köra class-transformer. Aktivera detta globalt med transform: true.
Detta konverterar även primitiva värden: en sträng från en route-parameter, '42', blir ett number när DTO-/parametertypen anger det. Utan transform förblir nästlade klasser vanliga objekt och era @Type-anvisningar ignoreras.
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
transform: true, // run class-transformer (required for @Type)
whitelist: true,
forbidNonWhitelisted: true,
}),
);
await app.listen(3000);
}
bootstrap();Validera arrayer med DTO:er
Arrayer med objekt behöver samma par, med ett tillägg: each: true. Då tillämpas den nästlade valideringen i @ValidateNested({ each: true }) på varje element i arrayen.
@Type(() => ItemDto) omvandlar varje rått element till en instans av ItemDto. Lägg till @IsArray() och vid behov @ArrayMinSize(1) för att även kontrollera själva samlingens form.
import { IsArray, ArrayMinSize, IsString, IsInt, Min, ValidateNested } from 'class-validator';
import { Type } from 'class-transformer';
class OrderItemDto {
@IsString()
sku: string;
@IsInt()
@Min(1)
quantity: number;
}
export class CreateOrderDto {
@IsArray()
@ArrayMinSize(1)
@ValidateNested({ each: true }) // validate every element
@Type(() => OrderItemDto)
items: OrderItemDto[];
}Djupt nästlade strukturer
Mönstret kan användas på hur många nivåer som helst. En order har items, och varje item har en egen nästlad discount. Varje nivå som går över till en annan klass upprepar paret @ValidateNested + @Type.
Valideringen går rekursivt uppifrån och ned: ordern validerar sin items-array, varje item validerar sitt discount-objekt och varje lövdekorator körs. Det finns ingen särskild ”deep”-flagga — ni använder bara samma två dekoratorer vid varje gräns.
import { ValidateNested, IsString, IsNumber, Max, Min } from 'class-validator';
import { Type } from 'class-transformer';
class DiscountDto {
@IsNumber()
@Min(0)
@Max(1)
rate: number;
}
class OrderItemDto {
@IsString()
sku: string;
@ValidateNested()
@Type(() => DiscountDto)
discount: DiscountDto;
}
export class CreateOrderDto {
@ValidateNested({ each: true })
@Type(() => OrderItemDto)
items: OrderItemDto[];
}whitelist tar bort okända egenskaper
whitelist: true tar bort alla egenskaper i den inkommande payloaden som saknar en valideringsdekorator i DTO:n. Detta är ett centralt säkerhetsskydd: klienter kan inte smyga in extra fält som isAdmin eller role i era entiteter.
Det är viktigt att whitelist fungerar rekursivt på validerade nästlade objekt. Om en nästlad AddressDto bara deklarerar city och zip tas även ett inskjutet country-fält i det nästlade objektet bort — men endast eftersom @ValidateNested + @Type fick validatorn att gå in i objektet.
forbidNonWhitelisted: avvisa eller ta bort
Det finns två sätt att hantera okända fält:
- whitelist: true — tar tyst bort okända egenskaper och fortsätter.
- whitelist + forbidNonWhitelisted: true — avvisar hela begäran med
400och anger den felande egenskapen.
För offentliga API:er är avvisning striktare och synliggör klientfel tidigt. Observera att forbidNonWhitelisted bara har effekt när whitelist också är aktiverat.
// Payload: { "city": "Austin", "zip": "73301", "hack": "x" }
// whitelist: true (only)
// -> { city: 'Austin', zip: '73301' } // 'hack' stripped
// whitelist: true + forbidNonWhitelisted: true
// -> 400 Bad Request
// -> message: ["property hack should not exist"]Ett rent class-validator-exempel som ni kan köra
Utanför NestJS fungerar samma motor direkt. Det här fristående kodexemplet bygger en nästlad instans med plainToInstance och validerar den med validateSync — exakt det som ValidationPipe gör internt.
Kör det för att se hur @ValidateNested + @Type synliggör ett nästlat fel.
import 'reflect-metadata';
import { IsString, IsInt, Min, ValidateNested, validateSync } from 'class-validator';
import { plainToInstance, Type } from 'class-transformer';
class ItemDto {
@IsString() sku!: string;
@IsInt() @Min(1) quantity!: number;
}
class OrderDto {
@ValidateNested({ each: true })
@Type(() => ItemDto)
items!: ItemDto[];
}
const payload = { items: [{ sku: 'A1', quantity: 0 }] };
const dto = plainToInstance(OrderDto, payload);
const errors = validateSync(dto);
console.log(JSON.stringify(errors[0].children[0].children, null, 2));Valfria och nullbara nästlade objekt
Ett nästlat objekt som kan saknas bör markeras med @IsOptional(). När det finns valideras det fortfarande; när det saknas hoppas det över. Kombinera detta med @ValidateNested och @Type som vanligt.
För arrayer gör @IsOptional() att hela arrayen kan utelämnas, medan @ArrayMinSize fortfarande kräver ett minimiantal när arrayen väl har skickats med. Behåll each: true så att befintliga element fortsätter att valideras.
import { IsOptional, ValidateNested, IsString } from 'class-validator';
import { Type } from 'class-transformer';
class BillingDto {
@IsString()
taxId: string;
}
export class UpdateAccountDto {
@IsOptional()
@ValidateNested()
@Type(() => BillingDto)
billing?: BillingDto;
}Vanliga fallgropar
Var uppmärksam på följande fel, som alla gör att ogiltiga data kan slinka igenom obemärkt:
- Glömmer @Type — det nästlade objektet förblir ett vanligt objekt och de underordnade dekoratorerna körs aldrig.
- Glömmer transform: true — pipen anropar aldrig class-transformer, så
@Typeignoreras. - Saknar each: true i arrayer — bara den första arrayen eller hela arrayen kontrolleras, inte varje element.
- Ingen import av reflect-metadata — dekoratorerna genererar inga metadata och valideringen gör ingenting.
- Inaktiverar whitelist — okända fält flödar direkt in i ert servicelager.
Snabb kontroll
Ni har en array med nästlade DTO:er som ska valideras. Vilken kombination krävs?
Sammanfattning
Ni vet nu hur man validerar nästlade DTO:er och DTO-arrayer i NestJS:
- @ValidateNested() talar om för validatorn att rekursivt gå igenom ett underordnat objekt; lägg till { each: true } för arrayer.
- @Type(() => Child) från class-transformer omvandlar rå JSON till riktiga klassinstanser så att de underordnade dekoratorerna körs.
- transform: true på ValidationPipe är obligatoriskt för att @Type ska få effekt.
- whitelist: true tar rekursivt bort odeklarerade egenskaper; forbidNonWhitelisted: true avvisar dem i stället med
400. - Importera alltid reflect-metadata och upprepa paret @ValidateNested + @Type vid varje klassgräns, oavsett hur djupt den ligger.
Lär dig TypeScript med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 20
- Lektioner
- 76
Vanliga frågor
Är lektionen ”Validering av nästlade och arraybaserade DTO:er” gratis?
Ja – hela texten till ”Validering av nästlade och arraybaserade DTO:er” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i NestJS: backend-API:er för företag, kan Ni uppgradera till CoddyKit PRO. Kursen i NestJS: backend-API:er för företag innehåller totalt 4 lektioner.
Vad lär jag mig i ”Validering av nästlade och arraybaserade DTO:er”?
Validera nästlade objekt och samlingar med @ValidateNested, @Type och borttagning via whitelist. Ni övar på NestJS: backend-API:er för företag med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig NestJS: backend-API:er för företag?
Du behöver inga förkunskaper. Utbildningen i NestJS: backend-API:er för företag på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”Validering av nästlade och arraybaserade DTO:er”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här NestJS: backend-API:er för företag-lektionen?
Ja. Varje NestJS: backend-API:er för företag-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- Validering av nästlade och arraybaserade DTO:er
- Anpassade validatorer och asynkrona begränsningar
- Formning av svar med ClassSerializerInterceptor
- Villkorad validering och dynamiska grupper