JSON을 YAML로 변환
JSON을 YAML로 변환하고 추가한 따옴표마다 이유를 설명 — 따옴표가 없으면 조용히 불리언·숫자·날짜가 되는 문자열을 보여 줍니다.
name: deploy
country: 'NO'
startsAt: '12:30'
mode: '0755'
version: '1.10'
released: '2024-01-30'
enabled: 'yes'
script: |-
set -e
npm run build
npm test
replicas: 3
tags:
- web
- edge
따옴표가 붙은 값: 6개. YAML 1.1에서만 필요한 것: 4개. 위의 스키마를 바꾸면 차이를 볼 수 있습니다.
country1.1 전용"NO"은(는) 불리언 false(으)로 읽힙니다.
startsAt1.1 전용"12:30"은(는) 60진법으로 750(으)로 읽힙니다.
mode"0755"은(는) 앞에 0이 있어 숫자 493(으)로 읽힙니다.
version"1.10"은(는) 숫자 1.1(으)로 읽힙니다.
released1.1 전용"2024-01-30"은(는) 텍스트가 아니라 날짜로 읽힙니다.
enabled1.1 전용"yes"은(는) 불리언 true(으)로 읽힙니다.
이 도구가 하는 일
JSON 문서를 YAML로 변환하고, 다른 어떤 변환기와도 달리 각 문자열이 왜 따옴표에 싸였는지 알려 줍니다. 그 두 번째 부분이 도구가 존재하는 이유입니다: 다른 모든 변환기는 출력을 건네주고 당신의 값 중 하나가 더는 문자열이 아님을 나중에 알아채게 둡니다.
변환은 한 방향으로 돕니다. YAML을 읽는 것은 쓰는 것보다 훨씬 큰 문제이고, 부분적으로만 옳은 YAML 파서는 없느니만 못합니다 — 당신의 파일을 받아들이고 불평 없이 잘못된 데이터를 건넵니다. 내보내기는 범위가 정해져 있어, 그것이 여기서 다루는 방향입니다.
변환기에 견해가 필요한 이유
JSON은 모든 것이 무슨 형인지 말합니다. 문자열은 따옴표가 있고 숫자는 없고, 세 번째 가능성은 없습니다. YAML은 대신 따옴표 없는 값의 형을 그 모양을 보고 정합니다: 불리언 패턴에 맞으면 불리언, 숫자에 맞으면 숫자, 아무것에도 맞지 않아야 비로소 텍스트로 남습니다.
그것이 YAML을 손으로 쓰기 좋게 만드는 것이자 그것으로의 변환을 판단이 필요한 일로 만드는 것입니다. 입력의 모든 문자열이 YAML이 해석하는 모든 패턴에 대해 확인되고, 맞으면 따옴표가 붙어야 합니다. 안전한 방향으로 틀리면 출력이 시끄럽고, 다른 방향으로 틀리면 값이 조용히 형을 바꿉니다.
노르웨이 문제와 그 친척
가장 잘 알려진 경우는 국가 코드 목록입니다. 노르웨이는 NO이고, YAML 1.1에서 따옴표 없는 토큰 NO는 불리언 false입니다. 국가를 나열하는 설정 파일이 노르웨이를 잃고 false를 얻는데, 어디서도 아무것도 오류를 보고하지 않습니다.
그것은 하나의 별난 규칙이 아니라 그 무리입니다. YAML 1.1은 y, Y, yes, no, on, off를 모든 대소로 불리언으로 읽어, 화학 기호, 스위치 위치, 물음에 대한 답을 걸립니다. 그리고 숫자 해석기는 더 이상합니다:
- 12:30은 750입니다. YAML 1.1은 콜론으로 나뉜 숫자를 60진법으로 읽어, 시각이나 시간의 길이가 정수가 됩니다.
- 0755는 493입니다. 앞의 0은 YAML 1.1에서 8진수를 뜻하고 — YAML 1.2에서는 같은 텍스트가 10진수 755라, 두 판이 어느 숫자인지로 어긋나지 어느 것인지로가 아닙니다.
- 1.10은 1.1입니다. 두 부분 버전 번호가 부동소수점이고 끝의 0이 사라집니다. 1.10에 고정된 의존성이 이제 1.1을 가리킵니다.
- 2024-01-30은 문자열이 아니라 날짜 객체입니다. YAML 1.1에 타임스탬프 형이 있기 때문입니다.
- 빈 문자열은 null이고, 맨 단어 null, Null, NULL과 물결표도 그렇습니다.
이것들 어느 것도 YAML의 버그가 아닙니다. 해석기가 맞는 텍스트에 대해 약속한 그대로 하는 것입니다. 유일한 방어는 맞는 것을 무엇이든 따옴표로 감싸는 것이고, 그것이 이 도구가 하는 것이자 소견 패널이 한 줄씩 설명하는 것입니다.
두 판, 그리고 왜 옛것이 기본인가
YAML 1.2는 2009년에 도착해 놀라운 해석기 대부분을 없앴습니다. 그 코어 스키마는 true와 false만 불리언으로 지키고, 60진법을 아예 떨구고, 타임스탬프 형이 없습니다. 1.2 아래에서 NO와 12:30과 2024-01-30은 모두 그저 문자열입니다.
함정은 실제로 당신의 파일을 읽는 것입니다. PyYAML은 YAML 1.1을 구현하고, PyYAML은 엄청난 양의 도구 뒤의 파서입니다 — Ansible, 오래된 Kubernetes 클라이언트, 무수한 스크립트. Go의 yaml.v3와 현행 js-yaml은 1.2를 따릅니다. 그래서 같은 문서가 누가 여느냐에 따라 두 다른 방식으로 읽힐 수 있고, 어디서나 안전한 유일한 출력은 1.1용으로 따옴표 붙인 것입니다.
그것이 여기 기본값입니다. 설정을 1.2로 바꿔도 아무것도 숨기지 않습니다 — 새 해석기로 다시 내보내고 소견 패널이 줄어들어, 어느 따옴표가 옛 스키마를 위한 것이었는지 정확히 볼 수 있습니다. 남는 것이 모든 파서가 필요로 하는 것입니다.
형이 아니라 구문을 깨뜨리는 문자열
두 번째 무리의 문자열이 다른 이유로 따옴표가 붙어야 합니다: YAML이 그것들을 다른 형으로 읽어서가 아니라, 애초에 텍스트로 파싱되지 않아서입니다.
- 공백이 따르는 콜론은 키를 끝냅니다. "note: time: now"는 값이 키 "time"인 키 "note"로 읽힐 것입니다.
- 해시가 따르는 공백은 주석을 시작하므로 그 뒤의 모든 것이 사라집니다.
- 앞의 -, ?, :, [, ], {, }, #, &, *, !, |, >, %, @ 나 백틱은 지시 문자이고 구조적인 무언가를 뜻합니다.
- 앞이나 뒤의 공백은 따옴표 없는 값이 지키지 못해, " x "가 "x"로 돌아옵니다.
- 값 어디의 탭이든 곧바로 거부됩니다 — PyYAML은 잘못 읽는 대신 문서 전체를 거부하므로, 이것은 요란하게 실패합니다.
작은따옴표는 충분한 곳 어디서나 쓰입니다. 이스케이프 규칙이 정확히 하나 — 아포스트로피는 두 번 쓴다 — 이고 큰따옴표가 들여오는 백슬래시 이스케이프보다 읽기 쉽기 때문입니다. 큰따옴표는 정말로 이스케이프가 필요한 경우를 위해 남겨 둡니다: 제어 문자, 탭, 그리고 블록을 쓸 수 없는 여러 줄 문자열입니다.
여러 줄 문자열과 chomping 지시자
줄바꿈을 담은 문자열 — 스크립트, 인증서, 산문 덩어리 — 이 대개 누군가 애초에 YAML을 원하는 이유입니다. JSON은 그것을 아주 긴 한 줄에 백슬래시-n 이스케이프로만 쓸 수 있고, YAML에는 파이프로 도입되는 리터럴 블록 스칼라가 있어 텍스트가 아래에 들여쓰여 읽을 수 있게 나타납니다.
미묘한 것은 끝의 줄바꿈에 무슨 일이 생기느냐이고, 그것은 chomping 지시자로 제어됩니다:
- 맨 파이프는 클립합니다: 블록이 끝의 줄바꿈을 몇 개 가지든 값은 정확히 하나를 얻습니다.
- 빼기가 따르는 파이프는 벗깁니다: 값은 하나도 얻지 못합니다.
- 더하기가 따르는 파이프는 지킵니다: 값은 그 모두를 얻습니다.
이 도구는 주어진 문자열에서 지시자를 골라, 값이 왕복을 정확히 살아남게 합니다. 알아 둘 만한 것은 기본 — 맨 파이프 — 이 사람이 손으로 쓰는 것이고, 두 줄바꿈이나 하나도 없이 끝난 문자열을 조용히 정규화하기 때문입니다.
블록 스칼라가 모든 것을 나를 수는 없고, 나를 수 없는 곳에서 출력이 큰따옴표로 물러나며 소견 패널이 이유를 말합니다. 캐리지 리턴은 살아남지 못합니다. 블록 스칼라가 줄바꿈을 정규화하기 때문입니다. 공백으로 시작하는 첫 줄은 여분의 들여쓰기로 읽혀 벗겨집니다. 그리고 공백으로 끝나는 줄은 사양이 지키지만 화면에서 보이지 않고 대부분의 편집기가 저장할 때 없애므로, 그것을 따옴표로 감싸는 것이 더 안전한 선택입니다 — 그것은 한계가 아니라 결정이고, 그렇게 보고됩니다.
하나보다 많은 문서
YAML에는 JSON에 없는 것이 있습니다: 파일이 세 붙임표로 나뉜 문서의 흐름을 담을 수 있습니다. 그것이 Kubernetes 매니페스트의 형식이고, JSON 배열이 그토록 자주 YAML 시퀀스 아닌 무언가가 되어야 하는 이유입니다.
여기 스위치는 최상위 배열의 각 요소를 저마다의 문서로 내보냅니다. 그리고 입력이 아예 단일 JSON 값이 아니라 각 줄이 저마다 파싱될 때, 그것은 NDJSON — 로그와 API 내보내기가 도착하는 줄 구분 형식 — 으로 읽혀 각 줄이 문서가 됩니다. 그 읽기는 추측이라 조용히가 아니라 출력 위에 보고됩니다.
그 물러남은 입력 전체가 파싱에 실패하고 모든 줄이 성공할 때만 적용되고, 그저 잘못된 문서는 그러지 않습니다. 구문 오류는 여전히 그것이 일어난 줄·열과 함께 구문 오류로 나타납니다.
변환이 지킬 수 없는 것
두 가지가 이 도구가 당신의 데이터를 보기 전에 둘 다 JSON 파싱 자체에서 잃히고, 어느 것인지 알아 둘 만합니다.
중복 키. JSON은 객체가 같은 키를 두 번 나열하게 허용하고 대부분의 파서가 조용히 마지막을 지킵니다. YAML은 중복을 아예 금하므로 출력은 유효하겠지만, 앞선 값은 이미 사라졌습니다 — 그리고 어떤 변환기도 받은 적 없는 것을 보고할 수 없습니다.
정수 정밀도. 약 9천조보다 큰 JSON 숫자는 배정밀도로 파싱되는 것을 살아남지 못해, 12345678901234567890 같은 ID가 반올림되어 돌아옵니다. 이것은 YAML 문제가 아니고 이 도구가 들여오는 문제도 아닙니다. 이 언어의 모든 JSON 파서에서 일어납니다. 큰 식별자가 중요하면 양쪽 모두에서 문자열에 속합니다.
출력에 대한 참고
들여쓰기는 늘 공백입니다. YAML이 들여쓰기의 탭을 아예 금하기 때문입니다 — 그것이 이 형식이 엄격한 몇 안 되는 것 중 하나입니다. 공백 2칸이 관례이고, 4칸은 일부 하우스 스타일이 원해 제공됩니다.
시퀀스는 그 키 아래로 들여쓰입니다. 그것도 들여쓰지 않은 형태도 합법적인 YAML이고 같은 것을 뜻합니다. 들여쓴 것이 대부분의 사람이 쓰고 대부분의 편집기가 올바르게 접는 것입니다.
빈 배열이나 객체는 대괄호나 중괄호 쌍으로 플로 스타일로 쓰입니다. 블록 스타일에는 빔을 나타낼 방도가 없기 때문입니다 — 다음 줄에 쓸 것이 없습니다.
출력은 줄바꿈으로 끝나고, 그것은 깔끔함이 아니라 하중을 담습니다. 블록 스칼라의 chomping은 그것에 따르는 줄바꿈에 대해 측정되므로, 마지막 줄바꿈 없는 파일의 맨 끝에 클립된 블록은 지켜야 했던 줄바꿈을 잃습니다.
자주 묻는 질문
- JSON은 이미 유효한 YAML인가요?
- YAML 1.2 아래에서는 그렇습니다: 사양이 그렇게 명시하고, 1.2 파서는 JSON 파일을 곧바로 읽습니다. 실무에서는 그다지 쓸모없습니다. 변환하는 이유는 가독성 — 주석, 블록 스칼라, 중괄호 없음 — 이고, JSON을 YAML 파일에 붙여넣으면 그중 아무것도 얻지 못하기 때문입니다. YAML 1.1 아래에서는 꼭 참은 아니고, 그것이 두 판을 가릴 만한 또 하나의 이유입니다.
- 필요 없어 보이는 따옴표가 붙은 이유는 무엇인가요?
- 거의 확실히 필요했습니다. YAML은 따옴표 없는 값을 패턴 대조로 형을 정하므로 NO, yes, off, 12:30, 0755, 1.10, 2024-01-30과 빈 문자열이 모두 문자열이기를 그칩니다. 소견 패널은 그 하나하나를 짚고 그것이 됐을 값을 보이므로, 믿는 대신 확인할 수 있습니다. YAML 1.2 파서를 노린다면 스키마를 바꾸면 1.1만 필요한 것이 없어집니다.
- 여기서 YAML 1.1과 1.2의 차이는 무엇인가요?
- 1.2는 대부분의 놀람을 일으키는 해석기를 떨궜습니다: yes/no/on/off가 더는 불리언이 아니고, 60진법이 없어지고, 타임스탬프 형이 없습니다. PyYAML은 1.1을 구현하고 아직 어디에나 있으므로 보수적인 출력이 기본이고, 1.2 설정은 무엇이 파일을 읽을지 알 때를 위해 있습니다.
- YAML을 JSON으로 되돌리는 변환도 되나요?
- 아니요, 그리고 그것은 의도입니다. YAML 읽기는 앵커, 별칭, 태그, 병합 키, 다섯 스칼라 스타일, 두 스키마 판이 필요하고, 그중 어느 것을 미묘하게 틀리면 파일을 받아들이고 담겼던 것과 다른 데이터를 돌려주게 됩니다. 그 실패는 조용해, 기능을 제공하지 않는 것보다 나쁘게 만듭니다.
- Kubernetes 스타일의 다중 문서 파일을 어떻게 얻나요?
- 최상위 배열의 각 요소를 저마다의 문서로 내보내는 스위치를 켜면 배열이 세 붙임표로 나뉜 문서가 됩니다. 입력이 대신 NDJSON — 로그와 API 내보내기가 흔히 그렇듯 한 줄에 JSON 객체 하나 — 이면 그것이 자동으로 감지되어 출력 위에 보고됩니다.
- 출력에 주석이 없는 이유는 무엇인가요?
- 입력에 없었기 때문입니다. 주석은 YAML에 있고 JSON에 없는 주된 것이고, 변환기가 그것을 지어낼 수 없습니다. 이것은 다른 방향으로도 기억할 만합니다: YAML 파일을 JSON으로 왕복시키면 그 안의 모든 주석이 사라집니다.
- 제가 붙여넣은 것이 서버로 전송되나요?
- 아니요. 파싱과 변환이 전적으로 브라우저 안에서 돕니다. 아무것도 업로드되거나 기록되지 않고, 네트워크 연결 없이 동작합니다.