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은 그것에 따르는 줄바꿈에 대해 측정되므로, 마지막 줄바꿈 없는 파일의 맨 끝에 클립된 블록은 지켜야 했던 줄바꿈을 잃습니다.
Kubernetes 매니페스트, 그리고 문자열로 남아야 하는 필드
Kubernetes는 매니페스트를 두 형식 어느 쪽으로든 읽습니다. 그 자신의 문서가 YAML을 관례라 부르고 JSON을 대안으로 들며, kubectl은 요청을 보낼 때 매니페스트를 JSON으로, 또는 API가 받는 다른 직렬화 형식으로 바꿉니다. 그러니 변환은 클러스터가 무엇을 받아 주느냐의 문제가 아닙니다. 당신이 보관하는 파일의 문제입니다: 검토자가 읽는 것이 YAML이고, 풀 리퀘스트의 차이가 읽히는 것이 YAML이며, 둘 가운데 주석을 실을 수 있는 쪽도 YAML뿐입니다. JSON은 보통 kubectl get -o json에서, 템플릿에서, 또는 객체를 돌려주는 API에서 옵니다.
- 한 파일, 여러 객체. 매니페스트는 세 붙임표로 나뉜 한 파일로 묶을 수 있고, 문서는 그것들이 나타난 순서대로 만들어진다고 분명히 말합니다 — 그래서 Service를 그것을 채우는 Deployment보다 위에 쓰는 것이 보통입니다. 최상위 배열의 각 요소를 저마다의 문서로 내보내는 스위치가 JSON 객체 목록을 그런 파일로 바꿉니다.
- 컨테이너의 환경 항목은 두 개의 문자열 필드입니다. API 문서가 name과 value를 둘 다 문자열로 정의하므로 "true"라는 JSON 값은 따옴표를 그대로 달고 나와야 합니다: 따옴표가 없으면 그것은 불리언이고, 불리언은 그 필드가 담도록 정의된 형이 아닙니다.
- 컨테이너 포트는 정수로 정의되어 있고, 그 문자열들에서 몇 줄 떨어져 앉아 있습니다. 둘은 반대의 처리를 필요로 하며 JSON이 이미 그 구별을 실어 옵니다 — 수는 그냥 수가 되고, 문자열은 YAML이 그것을 문자열로 읽기를 그칠 자리에서만 따옴표가 붙습니다.
- 레이블과 어노테이션은 문자열에서 문자열로 가는 사상입니다. 매니페스트 안에서 노르웨이 문제가 내려앉는 곳이 거기입니다: 값이 NO, on, off인 레이블은 YAML 1.1 파서에게 불리언이고, 값 1.10은 끝의 0을 잃는 부동소수점입니다.
환경 항목 세 개를 값이 모두 문자열인 JSON으로 주면 이렇게 변환됩니다:
env:
- name: DEBUG
value: 'true'
- name: REPLICAS
value: '3'
- name: COUNTRY
value: 'NO'셋 다 따옴표가 붙고, 소견 패널은 셋 다를 각각이 됐을 값과 함께 짚습니다: true는 불리언, 3은 수, NO는 불리언 false입니다. 판에 따라 달라지는 것은 마지막 하나뿐입니다 — 스키마를 1.2로 옮기면 그 따옴표가 떨어집니다. 1.2는 NO를 텍스트 말고 아무것으로도 읽지 않기 때문입니다. 다른 둘은 두 판 모두에서 따옴표를 지킵니다.
Docker Compose — 형식 자신의 문서가 YAML을 경고하는 곳
Compose 파일은 YAML이고, 그에 대한 Docker의 문서는 YAML 파싱에 관한 경고 둘을 싣고 있습니다. 제품 자신의 문서가 스스로의 직렬화 형식을 위험으로 짚는 일은 드물며, 두 경고 모두 이 도구가 있는 바로 그 까닭에 관한 것입니다: 텍스트여야 할 값을 파서가 다른 것으로 읽는 일.
- 포트. 문서는 HOST:CONTAINER 대응을 늘 따옴표 붙인 문자열로 주어야 한다고 말합니다. YAML의 60진법 부동소수점과의 충돌을 피하려는 것입니다. 따옴표가 없으면 22:22은 정수 1342입니다.
- 환경 값. 문서는 파서가 바꾸지 않도록 true, false, yes, no를 따옴표로 감싸 달라고 청합니다. 넷 가운데 둘은 YAML 두 판 모두에서 불리언이고, 둘 — yes와 no — 은 1.1에서만 그러하므로 소견 패널이 그것들을 다르게 표시합니다.
- 60진법 규칙이 닿는 것은 콜론 뒤의 수가 예순보다 작은 대응뿐입니다. 그것이 60진법 한 자리가 덮는 범위이기 때문입니다. 그래서 22:22은 여기서 따옴표가 붙고 8080:80은 그냥 남으며, 그 차이는 어느 포트가 중요한지에 대한 판단이 아니라 규칙입니다.
포트와 환경 값이 JSON에서 모두 문자열인 서비스는 이렇게 변환됩니다:
services:
proxy:
image: nginx
ports:
- '22:22'
- 8080:80
environment:
TLS_ENABLED: 'no'
DEBUG: 'true'그것이 문서가 청하는 출력이고, 기본 스키마가 그것을 만듭니다. 스키마를 그대로 두어야 할 가장 뚜렷한 이유이기도 합니다: 1.2로 옮기면 포트 대응과 no는 따옴표를 잃고 true는 자기 따옴표를 지킵니다. 1.2가 60진법을 버리고 불리언으로 true와 false만 남겼기 때문입니다. 1.2를 구현한 파서라면 결과를 옳게 읽습니다 — 그러나 Docker의 조언은 그런 조건 하나 없이 쓰여 있고, 그것을 따르는 값은 따옴표 두 쌍입니다.
자주 묻는 질문
- 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으로 왕복시키면 그 안의 모든 주석이 사라집니다.
- 제가 붙여넣은 것이 서버로 전송되나요?
- 아니요. 파싱과 변환이 전적으로 브라우저 안에서 돕니다. 아무것도 업로드되거나 기록되지 않고, 네트워크 연결 없이 동작합니다.
- kubectl의 JSON 출력을 YAML 매니페스트로 어떻게 변환하나요?
- 붙여넣고 YAML을 읽으세요. Kubernetes는 두 형식을 다 받습니다 — 그 문서가 YAML을 관례, JSON을 대안이라 부릅니다 — 그러니 변환하는 까닭은 클러스터가 무엇을 받느냐가 아니라 당신이 보관하는 파일입니다. 확인할 것은 따옴표입니다: 매니페스트는 API가 문자열로 정의하는 필드로 가득하고, 환경 값과 레이블·어노테이션 값도 그 안에 있으며, 바로 그것들이 YAML이 형을 바꿔 놓을 것들입니다. JSON이 여러 객체의 목록이라면 다중 문서 스위치가 그것을 한 파일로 만듭니다.
- 왜 Docker Compose는 내 포트를 따옴표 안에 두라고 하나요?
- YAML 1.1 파서에게 22:22은 수 한 쌍이 아니라 60진법의 한 수 — 1342이기 때문입니다. Docker의 Compose 문서는 바로 그 까닭으로 HOST:CONTAINER 대응이 늘 따옴표 붙은 문자열이어야 한다고 말하고, 같은 쪽이 환경 블록의 true, false, yes, no도 따옴표로 감싸 달라 청합니다. 둘 다 이 도구가 기본 스키마에서 하는 일이고, 소견 패널은 각 따옴표가 어느 규칙에서 왔는지 말합니다. 콜론 뒤의 수가 예순이거나 그보다 큰 대응, 이를테면 8080:80은 60진법 규칙 밖이라 그냥 남습니다.
- Kubernetes나 Docker Compose에는 어느 YAML 판을 골라야 하나요?
- 기본인 1.1입니다. 그것이 붙이는 따옴표는 모두 1.2 파서도 받아들이므로 보수적인 출력은 어느 쪽으로도 안전하고, Compose 문서의 경고 둘은 모두 1.1의 규칙에 관한 것입니다 — 60진법 포트 대응, 그리고 불리언으로서의 yes와 no. 1.2 설정은 오래된 스키마 때문에만 있는 따옴표가 어느 것인지 보이기 위해 있습니다. 출력은 그것을 잃고, 그것은 그 경고들이 청하는 바의 반대입니다.
관련 도구
- JSON → TypeScript 변환
JSON 샘플에서 TypeScript 인터페이스 추론.
- JSONPath 테스터
RFC 9535 JSONPath 쿼리를 JSON에 대해 테스트.
- Markdown 표 생성기
CSV, TSV, JSON에서 Markdown 표를 만들고 정렬합니다.
- PDF 병합
여러 PDF를 원하는 순서로 한 파일로 합칩니다 — 아무것도 업로드되지 않습니다.