MYMONDAY.ai
서비스스튜디오도구데이터·포맷73CSS 생성기19색상·이미지10인코딩·보안10웹·SEO11개발·데브옵스10파일·내보내기18계산기6가이드

YAML Dart 변환기

YAML 설정이나 데이터 파일을 YAML 1.2 로더가 돌려주는 값에 맞는 필드를 가진 Dart 클래스로 바꿉니다.

  • 브라우저에서 처리
  • 가입 없음
  • 무료

도구 작업 공간

예제

옵션

문서

---로 구분된 여러 문서가 있는 파일을 배열로 만들지(자동), 항상 배열로 만들지, 첫 문서만 쓸지 정합니다.

YAML 1.1 병합 키: <<: *base는 앵커의 키를 복사하며, 옆에 직접 쓴 키가 우선합니다. 끄면 <<를 일반 키로 둡니다.

YAML 입력

21줄314byte

결과

⌘/Ctrl + Enter로 복사
결과 · payload.dart
class Payload {
  final int id;
  final String status;
  final PayloadCustomer customer;
  final List<PayloadItem> items;
  final double total;
  final String shippedAt;
  final dynamic tracking;

  Payload({
    required this.id,
    required this.status,
    required this.customer,
    required this.items,
    required this.total,
    required this.shippedAt,
    this.tracking,
  });

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
        id: json['id'] as int,
        status: json['status'] as String,
        customer: PayloadCustomer.fromJson(json['customer'] as Map<String, dynamic>),
        items: (json['items'] as List<dynamic>).map((e0) => PayloadItem.fromJson(e0 as Map<String, dynamic>)).toList(),
        total: (json['total'] as num).toDouble(),
        shippedAt: json['shipped_at'] as String,
        tracking: json['tracking'],
      );

  Map<String, dynamic> toJson() => {
        'id': id,
        'status': status,
        'customer': customer.toJson(),
        'items': items.map((e0) => e0.toJson()).toList(),
        'total': total,
        'shipped_at': shippedAt,
        'tracking': tracking,
      };
}

class PayloadCustomer {
  final int id;
  final String name;
  final String email;
  final bool vip;

  PayloadCustomer({
    required this.id,
    required this.name,
    required this.email,
    required this.vip,
  });

  factory PayloadCustomer.fromJson(Map<String, dynamic> json) => PayloadCustomer(
        id: json['id'] as int,
        name: json['name'] as String,
        email: json['email'] as String,
        vip: json['vip'] as bool,
      );

  Map<String, dynamic> toJson() => {
        'id': id,
        'name': name,
        'email': email,
        'vip': vip,
      };
}

class PayloadItem {
  final String sku;
  final String name;
  final int qty;
  final double price;

  PayloadItem({
    required this.sku,
    required this.name,
    required this.qty,
    required this.price,
  });

  factory PayloadItem.fromJson(Map<String, dynamic> json) => PayloadItem(
        sku: json['sku'] as String,
        name: json['name'] as String,
        qty: json['qty'] as int,
        price: (json['price'] as num).toDouble(),
      );

  Map<String, dynamic> toJson() => {
        'sku': sku,
        'name': name,
        'qty': qty,
        'price': price,
      };
}
타입3
크기2.3kB

YAML 파일을 읽는 플러터나 Dart 앱은 Map<String, dynamic>을 뒤지는 대신 타입이 있는 모델을 원하기 마련입니다. 이 변환기는 yaml 라이브러리(YAML 1.2 코어 스키마)로 YAML을 읽고 앵커와 병합 키를 펼친 뒤, 매핑마다 final 필드, 이름 있는 매개변수 생성자, fromJson 팩토리, toJson 메서드를 갖춘 Dart 클래스 하나를 씁니다.

클래스 이름을 붙이기 전에 같은 위치의 값을 하나로 합칩니다. 매핑 목록은 모든 항목의 필드를 합친 항목 클래스 하나가 되고, 일부 항목에 없는 키는 널 허용 필드가 되어 값이 null이면 toJson에서 빠지며, 정수와 소수가 섞인 숫자 목록은 List<double>이 됩니다. 루트 타입 이름(기본 Payload, 파일 이름은 payload.dart)도 바꿀 수 있습니다.

입력하는 동안 결과가 갱신되며 API 응답, 앵커와 병합 키, 엣지 케이스 예제가 있습니다. 모든 처리는 브라우저 탭 안에서 이루어지고 업로드되지 않으며 입력은 20MiB까지입니다.

사용 방법

  1. YAML 붙여 넣기 또는 예제 고르기

    문서를 붙여 넣거나 .yaml 파일을 편집기에 끌어다 놓고, 예제 칩을 고를 수도 있습니다. 루트는 매핑이든 목록이든 되지만, 스칼라 하나는 이름 붙일 타입이 없어 오류가 납니다.

  2. 루트 클래스 이름 정하기

    루트 타입 이름 칸에 이름을 씁니다. PascalCase로 바뀌고 중첩 클래스는 그 이름이 앞에 붙으며(PayloadLimits), 내려받는 파일 이름은 payload.dart처럼 스네이크 표기가 됩니다.

  3. 문서와 병합 키를 읽는 방식 고르기

    문서가 여러 개일 때 자동은 목록을 만들고, 항상 배열은 문서 하나여도 그렇게 하며, 첫 문서만은 첫 문서만 남깁니다. 병합 키(<<) 펼치기는 물려받은 키를 클래스의 실제 필드로 만듭니다.

  4. 생성된 클래스 확인

    루트 클래스가 먼저 나오고 중첩 클래스가 만난 순서대로 이어집니다. 널 허용 필드, dynamic 필드, double 변환이 파일에 대해 아는 내용과 맞는지 확인하세요.

  5. 복사 또는 저장

    코드를 복사하거나 .dart 파일로 내려받습니다. 출력은 평범한 Dart이므로 동등 비교, copyWith, 코드 생성기 어노테이션은 직접 추가하세요.

작동 원리

YAML 값과 Dart 타입

타입은 파싱된 값에서 정해집니다. YAML 1.2는 true와 false만 불리언으로 읽으므로 debug: no는 String입니다. 날짜도 문자열이고, 정수는 int, 소수는 double입니다. 늘 null뿐이거나 [1, two]처럼 서로 다른 타입이 섞인 위치는 dynamic이 됩니다.

널 허용 필드에는 ?가 붙고, 일부 매핑에 없는 키는 널 허용이면서 생성자에서도 선택 인자가 됩니다. 단순한 as double 캐스트와 달리 double 필드는 (json['x'] as num).toDouble()로 디코딩하므로 정수 3이 들어와도 예외가 나지 않습니다.

YAMLDart비고
name: apiString
port: 8080int32비트를 넘는 정수도 int
ratio: 0.5double(x as num).toDouble()로 디코딩
debug: noString불리언은 YAML 1.1에서만
enabled: truebool
when: 2026-10-01String코어 스키마에는 타임스탬프 타입이 없음
region: ~ (단독)dynamic문자열과 함께 나오면 String?
tags: [web, edge]List<String>.map(...).toList()로 변환
mixed: [1, two]List<dynamic>
limits: {cpu: 0.5}class PayloadLimits경로에서 이름을 만듦
id: 9007199254740993String2^53을 넘으면 정확한 텍스트로 유지하고 알림 표시

숫자 1.0과 섞인 숫자 목록

코드 생성기는 YAML 표기가 아니라 평범한 숫자를 받습니다. 그래서 ratio: 1.0 하나만 있으면 숫자 1이므로 int 필드가 됩니다. 같은 필드에 [1.0, 2.5]처럼 다른 소수가 함께 있거나, 두 레코드가 price: 1.0과 price: 2.5를 가지면 그 위치는 double이 됩니다.

필드가 double이어야 하는데 샘플에 정수만 있다면 샘플에 소수 값을 하나 넣거나 타입을 직접 고치세요. double 디코더는 1과 1.5를 모두 받으므로 실제 데이터에는 안전한 선택입니다.

이름, 병합 키, 여러 문서

키는 camelCase 필드 이름이 되고, 원래 키는 fromJson과 toJson의 맵에 그대로 남습니다. Dart 예약어에는 Value가 붙어(class는 classValue), 한글처럼 ASCII 글자가 없는 키는 field가 되며 반복되면 숫자 접미사가 붙습니다.

별칭은 복사본으로 펼쳐지고 << 병합 키도 기본으로 펼쳐지므로, 앵커에서 물려받는 매핑은 물려받은 필드를 모두 갖습니다. 스위치를 끄면 <<에서 만든 필드가 중첩 클래스와 함께 나타납니다. 여러 문서는 typedef Payload = List<PayloadItem>;이 됩니다.

실제 예시

int, double, null이 있는 작은 설정
입력
name: api
port: 8080
ratio: 1.5
region: ~
출력
class Payload {
  final String name;
  final int port;
  final double ratio;
  final dynamic region;

  Payload({
    required this.name,
    required this.port,
    required this.ratio,
    this.region,
  });

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
        name: json['name'] as String,
        port: json['port'] as int,
        ratio: (json['ratio'] as num).toDouble(),
        region: json['region'],
      );

  Map<String, dynamic> toJson() => {
        'name': name,
        'port': port,
        'ratio': ratio,
        'region': region,
      };
}

ratio는 num을 거쳐 디코딩하고, null인 region은 dynamic이라 required도 널 허용 표시도 필요 없습니다.

1.0 하나는 int, 섞인 목록은 double
입력
ints: 1.0
mixed: [1.0, 2.5]
출력
class Payload {
  final int ints;
  final List<double> mixed;

  Payload({
    required this.ints,
    required this.mixed,
  });

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
        ints: json['ints'] as int,
        mixed: (json['mixed'] as List<dynamic>).map((e0) => (e0 as num).toDouble()).toList(),
      );

  Map<String, dynamic> toJson() => {
        'ints': ints,
        'mixed': mixed,
      };
}

생성기가 보는 ints는 숫자 1이지만, 목록에는 진짜 소수가 있어 모든 원소를 toDouble()로 바꿉니다.

예약어와 ASCII가 아닌 키
입력
class: x
max-conn: 5
한글: 1
출력
class Payload {
  final String classValue;
  final int maxConn;
  final int field;

  Payload({
    required this.classValue,
    required this.maxConn,
    required this.field,
  });

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
        classValue: json['class'] as String,
        maxConn: json['max-conn'] as int,
        field: json['한글'] as int,
      );

  Map<String, dynamic> toJson() => {
        'class': classValue,
        'max-conn': maxConn,
        '한글': field,
      };
}

필드 이름은 올바른 Dart이고 맵 키는 원래 표기를 유지하므로 데이터가 그대로 왕복합니다.

문서 두 개가 typedef와 널 허용 필드가 됨
입력
id: 1
name: a
---
id: 2
출력
typedef Payload = List<PayloadItem>;

class PayloadItem {
  final int id;
  final String? name;

  PayloadItem({
    required this.id,
    this.name,
  });

  factory PayloadItem.fromJson(Map<String, dynamic> json) => PayloadItem(
        id: json['id'] as int,
        name: json['name'] as String?,
      );

  Map<String, dynamic> toJson() => {
        'id': id,
        if (name != null) 'name': name,
      };
}

자동 모드는 문서 둘을 목록으로 만듭니다. name은 한쪽에만 있어 널 허용 선택 필드이고, 값이 null이면 toJson에서 빠집니다.

큰 정수, 섞인 목록, bool 목록
입력
id: 9007199254740993
mixed: [1, two]
flags: [true, false]
출력
class Payload {
  final String id;
  final List<dynamic> mixed;
  final List<bool> flags;

  Payload({
    required this.id,
    required this.mixed,
    required this.flags,
  });

  factory Payload.fromJson(Map<String, dynamic> json) => Payload(
        id: json['id'] as String,
        mixed: json['mixed'] as List<dynamic>,
        flags: (json['flags'] as List<dynamic>).map((e0) => e0 as bool).toList(),
      );

  Map<String, dynamic> toJson() => {
        'id': id,
        'mixed': mixed,
        'flags': flags,
      };
}

2^53을 넘는 정수는 String이고 정확한 텍스트로 유지했다는 알림이 나옵니다. 섞인 목록은 List<dynamic>이 되어 그대로 전달됩니다.

자주 하는 실수

  • fromJson은 Map<String, dynamic>을 기대함

    생성된 팩토리는 jsonDecode가 돌려주는 Map<String, dynamic>으로 캐스트합니다. YAML 패키지가 돌려주는 맵은 그 타입이 아니므로, 예를 들어 JSON으로 인코딩했다가 디코딩하는 식으로 먼저 변환하세요.

  • 1.0 하나는 int 필드가 됨

    생성기가 보는 것은 숫자 1이라서 ratio: 1.0은 int ratio가 되고, 나중에 실제 1.5가 오면 as int 캐스트가 예외를 냅니다. 샘플에 소수 값을 넣거나 타입을 직접 double로 고치세요.

  • null은 널 허용 타입이 아니라 dynamic

    모든 샘플에서 ~인 값은 알 수 있는 타입이 없어 dynamic으로 적힙니다. 운영에서 문자열이라면 String?으로 고치세요.

  • 선택 여부는 여러 매핑을 보고 추정

    같은 위치의 일부 매핑에 키가 없거나 null일 때만 널 허용 선택 필드가 됩니다. 샘플 레코드가 하나면 모든 키가 필수이므로 여러 개를 붙여 넣으세요.

  • 로더도 YAML 1.2와 같은 규칙이어야 함

    여기서 yes는 String이고 Dart의 yaml 패키지도 1.2 코어 스키마를 따르지만, 다른 도구는 불리언으로 읽을 수 있습니다. "0123"이나 국가 코드 "NO"처럼 텍스트로 남아야 하는 값은 따옴표로 감싸세요.

  • 날짜는 문자열

    YAML 날짜는 String 필드입니다. DateTime이 필요하면 코드에서 DateTime.parse로 변환하세요.

자주 묻는 질문

최상위가 목록인 YAML도 되나요?

네. 루트 목록은 typedef Payload = List<PayloadItem>;과 항목 클래스가 됩니다. 문서가 여러 개인 파일도 자동 모드에서는 이런 목록이 됩니다.

yes가 왜 String인가요?

YAML 1.2 코어 스키마에서는 true와 false만 불리언이라 yes, no, on, off는 일반 문자열이고, 생성된 필드는 String입니다.

null과 선택 필드는 어떻게 타입이 정해지나요?

늘 null뿐인 값은 dynamic입니다. 일부 매핑에서 null이거나 없는 키는 T?가 되어 생성자에서 선택 인자이고, null이면 toJson에서 빠집니다.

double을 왜 num을 거쳐 디코딩하나요?

JSON이나 YAML에서는 클래스가 double을 원하는 자리에 정수 3이 들어올 수 있습니다. (json['x'] as num).toDouble()은 둘 다 받지만 as double 캐스트는 예외를 냅니다.

병합 키도 펼치나요?

기본값은 펼침이라 <<: *anchor로 물려받은 키가 클래스의 필드가 됩니다. 병합 키 펼치기를 끄면 <<에서 만든 필드가 대신 나옵니다.

루트 클래스 이름을 바꿀 수 있나요?

네, 루트 타입 이름에서 바꿉니다. app config는 AppConfig가 되고 내려받는 파일은 app_config.dart입니다.

YAML이 업로드되나요?

아니요. 파싱과 코드 생성은 브라우저 탭 안에서 실행되며 서버로 전송되지 않습니다. 입력은 20MiB까지입니다.

마지막 업데이트: