Spring til indhold
dto.dk

Eksempler

Den samme DTO i seks sprog

De fleste moderne sprog har en kort måde at skrive et uforanderligt dataobjekt på. Her er en ordre-DTO med en liste af linjer skrevet i seks sprog, så du kan sammenligne.

TypeScript

I TypeScript beskriver man typisk formen med en interface eller en type. Den findes kun ved kompilering, så data fra et API bør stadig valideres, når programmet kører. readonly forhindrer, at felterne bliver ændret ved en fejl.

TypeScript
interface OrdrelinjeDto {
  readonly varenummer: string;
  readonly antal: number;
  readonly stykpris: number;
}

interface OrdreDto {
  readonly id: number;
  readonly kundeId: number;
  readonly linjer: readonly OrdrelinjeDto[];
  readonly oprettet: string;
}

C#

En record giver uforanderlige egenskaber, sammenligning på værdi og en pæn ToString() med én linje kode.

C#
public record OrdrelinjeDto(string Varenummer, int Antal, decimal Stykpris);

public record OrdreDto(
    int Id,
    int KundeId,
    IReadOnlyList<OrdrelinjeDto> Linjer,
    DateTimeOffset Oprettet);

Java

Siden Java 16 er record en fast del af sproget. Felterne er final, og du får konstruktør, adgangsmetoder, equals og hashCode automatisk.

Java
public record OrdrelinjeDto(String varenummer, int antal, BigDecimal stykpris) {}

public record OrdreDto(
        long id,
        long kundeId,
        List<OrdrelinjeDto> linjer,
        Instant oprettet) {

    public OrdreDto {
        linjer = List.copyOf(linjer); // listen kan ikke ændres udefra
    }
}

PHP

Fra PHP 8.2 kan en hel klasse erklæres readonly. Sammen med constructor promotion bliver en DTO meget kort.

PHP
final readonly class OrdrelinjeDto
{
    public function __construct(
        public string $varenummer,
        public int $antal,
        public string $stykpris, // beløb som tekst, så der ikke opstår afrundingsfejl
    ) {}
}

final readonly class OrdreDto
{
    /** @param list<OrdrelinjeDto> $linjer */
    public function __construct(
        public int $id,
        public int $kundeId,
        public array $linjer,
        public DateTimeImmutable $oprettet,
    ) {}
}

Python

En dataclass med frozen=True kan ikke ændres, efter den er oprettet. Brug en tuple i stedet for en liste, hvis samlingen også skal være uforanderlig.

Python
from dataclasses import dataclass
from datetime import datetime
from decimal import Decimal


@dataclass(frozen=True)
class OrdrelinjeDto:
    varenummer: str
    antal: int
    stykpris: Decimal


@dataclass(frozen=True)
class OrdreDto:
    id: int
    kunde_id: int
    linjer: tuple[OrdrelinjeDto, ...]
    oprettet: datetime

Kotlin

En data class med val-felter er Kotlins måde at skrive en DTO på.

Kotlin
data class OrdrelinjeDto(
    val varenummer: String,
    val antal: Int,
    val stykpris: BigDecimal,
)

data class OrdreDto(
    val id: Long,
    val kundeId: Long,
    val linjer: List<OrdrelinjeDto>,
    val oprettet: Instant,
)

Penge og datoer

Læg mærke til, at beløb ikke er kommatal (float eller double) i eksemplerne. Kommatal kan ikke gemme alle decimaltal præcist, så brug en decimaltype, heltal i øre eller en tekst. Datoer sendes mest sikkert som tekst i ISO 8601-format med tidszone, fx 2026-03-01T09:30:00+01:00.