JSON 복구
끝쉼표, 작은따옴표, 주석, 파이썬 리터럴을 고치고 모든 변경 내역을 보여 줍니다.
붙여 넣은 것은 여러분의 브라우저를 떠나지 않습니다. connect-src 허용 목록 덕분에 이는 약속이 아니라 브라우저가 강제하는 보장입니다. 직접 확인하기
복구는 거의 JSON인 것을 유효한 JSON으로 만듭니다. 끝쉼표, 작은따옴표, 따옴표 없는 키, 주석, 파이썬 리터럴, 둥근 따옴표, 닫히지 않은 괄호, 눈에 보이지 않는 공백.
중요한 건 결과물이 아니라 변경 내역입니다. 페이로드를 조용히 다시 쓰는 복구 도구는 아예 없느니만 못합니다. 무엇을 대신 결정했는지 알 수 없기 때문입니다. 모든 변경은 행과 열과 함께 나열되고, 판단이 필요한 변경은 그렇지 않은 변경과 따로 표시됩니다.
추측 없이 고치는 것
이 경우들은 합리적인 해석이 하나뿐이므로, 변경 내역에 적는 것 외에는 말없이 적용됩니다.
- 끝쉼표와 중복 쉼표
- 제거합니다. JavaScript와 JSON5에서는 합법이지만 JSON에서는 절대 아닙니다.
- 작은따옴표 문자열
- 큰따옴표로 바꾸고, 안쪽 아포스트로피가 결과를 깨뜨리지 않도록 내용을 다시 이스케이프합니다.
- 따옴표 없는 키
- 따옴표를 붙입니다. JavaScript는 맨 식별자를 키로 쓸 수 있지만 JSON은 안 됩니다.
- 주석
- // 형태와 /* */ 형태 모두 제거합니다.
- 파이썬 리터럴
- True, False, None을 true, false, null로 바꿉니다.
- 둥근 따옴표
- 자동 교정이 만들어 내는 둥근 따옴표를 곧은 ASCII 따옴표로 바꿉니다.
- 잘못된 공백
- 줄바꿈 없는 공백과 그 친척들은 보통 공백으로 바꾸고, 폭이 0인 문자는 제거합니다.
- 바이트 순서 표식
- 문서 맨 앞에서 떼어 냅니다.
- 빠진 쉼표와 콜론
- 문법상 의도가 분명한 자리에 넣습니다.
- 문자열 안의 날 제어 문자
- 이스케이프합니다. 실제 줄바꿈은 \n이 됩니다.
판단이 필요한 것으로 표시하는 것
이것들은 의미를 바꾸고, 모두에게 맞는 기본값은 없습니다. 적용하되 따로 나열하고, 설정으로 바꿀 수 있습니다.
- 앞자리 0
- 기본값은 값을 따옴표로 감싸는 것입니다. 02134는 문자열 "02134"가 됩니다. 실제 데이터에서 앞자리 0은 거의 언제나 우편번호, 계좌번호, SKU이고, 지워 버리면 값이 조용히 망가집니다. 정말 숫자라면 정책을 숫자 변환으로 바꾸면 2134가 됩니다.
- NaN, Infinity, undefined
- null로 바꿉니다. 대부분의 인코더가 넣는 값이기도 합니다. 파이썬의 json.dumps는 기본적으로 NaN과 Infinity를 내보내므로, 발생 지점에서 잡으려면 allow_nan=False를 넘기세요.
- 값 자리에 온 맨 단어
- 문자열로 따옴표를 붙입니다. {"status": pending}은 {"status": "pending"}이 됩니다. 대체로 맞고 가끔 틀립니다.
- 닫히지 않은 괄호
- 문서 끝에서 닫습니다. 오타가 아니라 파일이 잘린 경우라면 데이터가 빠진 채로 유효한 JSON이 만들어지므로, 이 변경은 항상 목록에 남깁니다.
- NDJSON
- 완결된 값이 한 줄에 하나씩 여러 개 있으면 기본적으로 배열로 감쌉니다. 첫 레코드만 남기거나, 입력을 그대로 두는 선택도 있습니다.
하지 않는 것
구조를 지어내지 않습니다. 입력이 JSON에서 너무 멀면 복구는 실패하고, 해결하지 못한 오류를 알려 줍니다. 파싱은 되지만 아무 뜻도 없는 결과를 만들어 내지는 않습니다.
또 정해진 횟수만큼만 반복합니다. 한 번의 처리가 앞선 처리에서 가려져 있던 문제를 드러낼 수는 있지만, 과정은 무한히 돌지 않고 수렴합니다.
How to do this in code
코드로 같은 일을 하는 방법과, 솔직한 단서 하나. 소비하는 쪽에서 느슨하게 파싱하고 있다는 건 대개 위쪽 어딘가가 잘못된 JSON을 만들어 내고 있고 앞으로도 계속 그러리라는 뜻입니다.
py Python, dict repr
ast.literal_eval은 리터럴 구조만 평가하므로 eval과 달리 임의의 코드를 실행할 수 없습니다.
import ast, json
# A Python dict printed with str() or print() is not JSON.
text = "{'name': 'Priya', 'active': True}"
value = ast.literal_eval(text) # safe: literals only, no eval
clean = json.dumps(value) # '{"name": "Priya", "active": true}' js JavaScript, JSON5
JSON5는 제대로 된 명세가 있는 상위 집합이라, 임시로 만든 느슨한 파서보다 더 나은 목표입니다.
import JSON5 from 'json5';
// Accepts comments, trailing commas, unquoted keys, single
// quotes, hex numbers and more.
const value = JSON5.parse(text);
const strict = JSON.stringify(value); ts TypeScript, JSONC
import { parse } from 'jsonc-parser';
// What VS Code uses for its own settings files: comments and
// trailing commas, and nothing else.
const errors: ParseError[] = [];
const value = parse(text, errors); sh Shell
# Strip comments and trailing commas with jq's relaxed reader
jq --args . <<< "$text"
# Or normalise a JSON5 file
npx json5 -c config.json5 > config.json 자주 묻는 질문
- 복구가 제 데이터를 바꾸는 경우가 있나요?
- 판단이 필요한 항목으로 나열된 방식으로만 바뀌며, 그 하나하나가 행과 열과 함께 변경 내역에 남습니다. 안전한 복구는 문법에만 손을 댑니다. 판단이 마음에 들지 않으면 설정을 바꾸고 다시 실행하세요.
- 왜 02134가 숫자 2134가 아니라 문자열이 되나요?
- 따옴표를 붙이는 건 정보를 잃지 않고, 0을 떼는 건 잃기 때문입니다. 실제 데이터에서 앞자리 0은 거의 언제나 의미가 있고, 우편번호를 조용히 더 작은 숫자로 바꿔 버리는 변환기야말로 이 사이트가 막으려는 종류의 조용한 손상입니다. 0을 떼는 선택지는 클릭 한 번 거리에 있습니다.
- 문서를 복구하지 못했다고 나옵니다. 이제 어떻게 하나요?
- 검증기에 넣어 보세요. 복구는 고치는 방법이 하나로 정해지는 문제만 다룹니다. 구조가 정말로 복원 불가능한 문서는 무엇을 의도했는지 사람이 판단해야 합니다.