TOML JSON 변환, 문법이 이렇게 바뀝니다
![TOML → JSON 탭이 선택된 화면으로, 위 입력창에 [database] 테이블과 [[posts]] 테이블 배열이 담긴 TOML이 있고 아래에 중첩 객체와 객체 배열로 변환된 JSON 결과가 표시되어 있습니다.](/images/blog/toml-converter/01-result.webp)
TOML을 JSON으로 바꿀 때 헷갈리는 건 계산이 어려워서가 아니라, 어떤 문법이 어떤 모양이 되는지 대응표가 머릿속에 없기 때문입니다. 결론부터 말하면 대응은 단순합니다. [table]은 중첩 객체, [[table]]은 객체 배열, 점(.)으로 이은 키와 인라인 테이블 { }은 모두 객체가 됩니다.
이 글은 설정 파일을 TOML과 JSON 사이에서 옮겨 담는 분을 위해, 각 문법 요소가 실제로 어떤 결과가 되는지 입출력으로 짚습니다.
요약 ①
[table]은 중첩 객체로,[[table]]은 객체 배열로, 점(.) 키와 인라인 테이블{ }은 모두 객체로 바뀝니다. ② 반대로 JSON → TOML은 최상위가 반드시 객체여야 하고, 값이null인 키는 TOML에 null이 없어 통째로 사라집니다. ③ 날짜처럼 보이는 값은 문자열로 남고,1_000_000같은 밑줄 숫자는 밑줄을 뗀1000000이 됩니다.
설정은 TOML인데 도구는 JSON만 받을 때
TOML은 설정 파일 형식으로 널리 쓰입니다. Rust의 Cargo.toml, 파이썬의 pyproject.toml, 여러 정적 사이트 생성기의 config.toml이 대표적입니다.
문제는 그 설정을 JSON만 받는 다른 도구나 스크립트에 넘겨야 할 때 생깁니다. 예를 들어 pyproject.toml의 설정 일부를 JSON 기반 검증 도구에 넣거나, 반대로 JSON으로 관리하던 설정을 TOML을 쓰는 도구로 옮기는 경우입니다.
이때 손으로 옮기다 보면 [tool.black] 같은 중첩 테이블이 어디까지 한 객체인지, [[tool.poetry.source]] 같은 이중 대괄호가 배열인지 객체인지 헷갈려 구조가 어긋나기 쉽습니다. 형식 자체는 단순한데, 대응 규칙을 모르면 실수가 나는 지점입니다.
도구 없이 문법을 하나씩 대응시키는 방법
먼저 원리입니다. TOML은 원래 해시 테이블(키-값 묶음, 즉 딕셔너리)에 정확히 대응되도록 설계된 형식입니다. 그래서 JSON의 객체와 짝이 잘 맞고, 대응 규칙도 몇 개로 정리됩니다.
규칙은 다섯 개입니다.
키 = 값→"키": 값으로 한 쌍이 그대로 옮겨집니다.[owner]아래 줄들 →"owner": { ... }로 묶인 중첩 객체가 됩니다.owner.name = "홍길동"처럼 점(.)으로 이은 키 →[owner]를 쓴 것과 똑같이"owner": { "name": "홍길동" }가 됩니다.[[posts]]가 반복되면 →"posts": [ {...}, {...} ]객체들의 배열이 됩니다. 대괄호가 두 겹인 것이 "배열"의 신호입니다.{ x = 1, y = 2 }인라인 테이블 →{ "x": 1, "y": 2 }객체가 됩니다.
예를 들어 아래 TOML은
title = "블로그 설정"
version = 2
tags = ["seo", "auto", "blog"]
[database]
host = "127.0.0.1"
port = 5432
[[posts]]
title = "첫 글"
views = 120
[[posts]]
title = "둘째 글"
views = 45
이렇게 바뀝니다.
{
"title": "블로그 설정",
"version": 2,
"tags": [
"seo",
"auto",
"blog"
],
"database": {
"host": "127.0.0.1",
"port": 5432
},
"posts": [
{
"title": "첫 글",
"views": 120
},
{
"title": "둘째 글",
"views": 45
}
]
}
[database]가 "database" 객체로, [[posts]]가 "posts" 배열로 접힌 것이 한눈에 보입니다.
손으로 옮긴 결과가 맞는지 확인하고 싶다면 표준 파서를 거치면 됩니다. 파이썬 3.11부터는 표준 라이브러리에 읽기 전용 TOML 파서 tomllib이 들어 있어, 별도 설치 없이 다음 한 줄로 같은 변환을 볼 수 있습니다.
python3 -c "import tomllib,json; print(json.dumps(tomllib.load(open('config.toml','rb')), indent=2, ensure_ascii=False))"
이 방식은 정식 파서라 문법 오류가 있으면 오류로 알려 준다는 장점이 있습니다. 다만 파일을 만들고 명령어를 치는 과정이 매번 번거롭고, 반대 방향(JSON → TOML)은 표준 라이브러리에 쓰기 도구가 없어 라이브러리를 따로 깔아야 합니다.
저희 도구로 확인하기.
붙여넣으면 브라우저에서 바로 TOML↔JSON 양방향 변환. 설치·회원가입 없이 무료이고 입력은 서버로 전송되지 않습니다.
![TOML → JSON 탭이 선택된 화면으로, 위 입력창에 [database] 테이블과 [[posts]] 테이블 배열이 담긴 TOML이 있고 아래에 중첩 객체와 객체 배열로 변환된 JSON 결과가 표시되어 있습니다.](/images/blog/toml-converter/01-result.webp)
결과를 읽을 때 헷갈리는 지점
대응만 알면 TOML → JSON 방향은 거의 헷갈리지 않습니다. 오해는 주로 반대 방향과, 몇 가지 값 처리에서 생깁니다. 자주 나오는 것만 정리하면 이렇습니다.
| 상황 | 결과 |
|---|---|
| JSON 최상위가 배열·숫자·문자열 | "TOML 최상위는 객체여야 합니다" 오류 |
값이 null인 키 | TOML에 null이 없어 그 키가 통째로 생략됨 |
"2026-07-17" 같은 날짜 문자열 | 따옴표 붙은 문자열 그대로 유지 |
1_000_000 밑줄 숫자 | 밑줄을 뗀 1000000 숫자로 |
# 주석 (따옴표 밖) | 결과에서 제거됨 |
최상위는 반드시 객체여야 합니다. JSON → TOML 방향에서 [1, 2, 3]처럼 최상위가 배열이거나 그냥 숫자·문자열 하나면 변환기는 "TOML 최상위는 객체(오브젝트)여야 합니다"라고 알립니다. TOML은 파일 전체가 하나의 키-값 묶음이라, 이름 없는 배열이 맨 바깥에 올 수 없기 때문입니다. { "items": [1, 2, 3] }처럼 키로 한 번 감싸면 변환됩니다.
null인 키는 사라집니다. TOML에는 null이라는 값 자체가 없습니다. 그래서 JSON에 "nickname": null이 있으면 TOML 결과에는 nickname 줄이 아예 나오지 않습니다. 값이 비어서가 아니라 키까지 통째로 빠지는 것이라, 결과를 다시 JSON으로 되돌리면 그 키는 없어져 있습니다.
날짜처럼 보여도 문자열입니다. TOML에는 원래 날짜·시간 타입이 있지만, 이 변환기는 그 부분을 단순화해 2026-07-17 같은 값을 날짜 타입이 아니라 문자열로 담습니다. 그래서 JSON 결과에 "2026-07-17"처럼 따옴표가 붙습니다. 숫자로 잘못 인식돼 값이 손상되는 일은 없습니다.
숫자의 밑줄은 자릿수 구분입니다. TOML은 1_000_000처럼 밑줄로 자릿수를 끊어 읽기 쉽게 쓸 수 있습니다. 변환기는 밑줄을 떼고 1000000이라는 숫자로 바꿉니다. JSON에는 밑줄 표기가 없으니 자연스러운 결과입니다.
정리
[table]은 중첩 객체,[[table]]은 객체 배열, 점(.) 키와 인라인 테이블{ }은 모두 객체로 바뀝니다.- JSON → TOML은 최상위가 반드시 객체여야 하며, 배열·숫자만 넣으면 오류가 납니다.
- 값이
null인 키는 TOML에 null이 없어 결과에서 통째로 빠집니다. - 날짜처럼 보이는 값은 문자열로 유지되고,
1_000_000같은 밑줄 숫자는 밑줄을 뗀 숫자가 됩니다. - 손으로 옮긴 결과는 파이썬
tomllib같은 표준 파서로 다시 확인할 수 있습니다.
붙여넣으면 브라우저에서 바로 TOML↔JSON 양방향 변환. 설치·회원가입 없이 무료이고 입력은 서버로 전송되지 않습니다.
자주 묻는 질문
TOML의 [[ ]] 이중 대괄호는 JSON에서 뭐가 되나요?
같은 이름의 [[posts]] 블록이 여러 번 나오면 그 이름의 객체 배열, 즉 "posts": [ { ... }, { ... } ]가 됩니다. 대괄호 한 겹인 [posts]는 하나의 중첩 객체, 두 겹인 [[posts]]는 배열이라는 점만 구분하면 됩니다.
JSON을 TOML로 바꿨더니 오류가 납니다. 왜인가요?
JSON의 최상위가 객체가 아닐 때 그렇습니다. [1, 2, 3]처럼 배열이거나 숫자·문자열 하나만 있으면 "TOML 최상위는 객체여야 합니다" 오류가 납니다. TOML은 파일 전체가 키-값 묶음이라, { "items": [1, 2, 3] }처럼 키로 한 번 감싸 주면 변환됩니다.
날짜를 넣었더니 따옴표가 붙은 문자열로 나옵니다.
정상입니다. 이 변환기는 날짜·시간을 단순화해 문자열로 다루기 때문에 2026-07-17이 "2026-07-17"로 나옵니다. 값이 바뀌거나 깨지는 것이 아니라 타입만 문자열로 유지되는 것입니다.
입력한 설정이 서버로 전송되나요?
아니요. 모든 변환은 브라우저 안에서 처리되며, 입력한 TOML·JSON은 서버로 전송되거나 저장되지 않습니다.
