JSON → JSON Schema

JSON을 붙여넣으면 JSON Schema draft-07 즉시 생성. 타입, 필수 필드, 중첩 구조 자동 추론. 무료, 브라우저에서 처리.

  • 브라우저에서 처리
  • 데이터가 브라우저 밖으로 나가지 않습니다
  • 무료 · 회원가입 불필요
입력, 생성된 스키마, 오류 메시지를 지웁니다. 도구 안에서 Ctrl/⌘+L로도 지우고 JSON 입력으로 포커스를 돌립니다.
샘플 JSON을 수정하거나 데이터를 입력하세요. 입력이 바뀔 때마다 draft-07 JSON Schema를 즉시 생성합니다. 배열은 모든 요소를 병합하며 모든 샘플 객체에 null이 아닌 값으로 있는 키를 필수로 지정합니다.
JSON Schema (draft-07)
생성된 스키마 전체를 복사합니다. 출력은 읽기 전용입니다. 편집기에 붙여넣어 제약 조건이나 필수 필드를 조정하세요. 빈 출력은 복사하지 않습니다.

JSON을 입력하면 draft-07 스키마를 생성합니다.

예시·자세한 설명·자주 묻는 질문 실제 출력이 있는 예시, 다른 도구와의 차이, 자주 묻는 질문.

JSON Schema란

JSON Schema는 JSON 데이터의 구조를 JSON으로 적는 사양입니다. 필드마다 타입, 필수 여부, 중첩 객체의 형태를 정의하고, Ajv 같은 검증기가 이를 기준으로 데이터를 검사합니다. API 입력 검사, 코드 생성, 문서 작성에 쓰입니다. 이 도구는 샘플 JSON에서 draft-07 스키마를 추론해 처음부터 손으로 쓰는 수고를 덜어 줍니다.

출력 이해하기

생성된 스키마에는 항상 draft-07을 가리키는 $schema가 포함됩니다. 객체 속성은 JSON 키에서 추론되고, required 배열에는 null이 아닌 모든 키가 나열됩니다. 배열의 items는 실제 요소에서 타입을 추론합니다.

생성 후 개선 포인트

생성된 스키마는 출발점입니다. 일반적인 개선 사항으로는 필드에 description 추가, minLength나 pattern으로 문자열 제약 강화, 선택적 속성을 required에서 제거, 알려진 값 집합에 enum 추가 등이 있습니다.

변환 예시

입력:

{
  "orderId": 1001,
  "total": 59.9,
  "coupon": null,
  "items": [{ "sku": "A1", "qty": 2 }],
  "tags": []
}

출력:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "orderId": { "type": "integer" },
    "total": { "type": "number" },
    "coupon": { "type": "null" },
    "items": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "sku": { "type": "string" },
          "qty": { "type": "integer" }
        },
        "required": ["sku", "qty"]
      }
    },
    "tags": { "type": "array", "items": {} }
  },
  "required": ["orderId", "total", "items", "tags"]
}
  • 정수는 integer, 소수는 number가 됩니다. qty가 1.5가 될 수 있으면 number로 바꾸세요.
  • 샘플의 coupon은 null이라 타입이 null이고 required에도 들어가지 않습니다. 문자열도 올 수 있으면 타입을 ["string", "null"]로 바꿉니다.
  • 빈 배열은 "items": {}가 되어 어떤 요소든 통과합니다.

카카오 로컬 API 응답으로 만들기

카카오 로컬 API 문서의 응답 예제를 그대로 넣어 보면, 같은 이름의 필드도 API마다 타입이 다르다는 점이 스키마에 드러납니다. 먼저 키워드로 장소 검색 응답(문서 예제에서 필드 일부만 남김)입니다.

{
  "meta": {
    "same_name": { "region": [], "keyword": "카카오프렌즈", "selected_region": "" },
    "pageable_count": 14,
    "total_count": 14,
    "is_end": true
  },
  "documents": [
    { "place_name": "카카오프렌즈 코엑스점", "distance": "418", "phone": "02-6002-1880", "x": "127.05902969025047", "y": "37.51207412593136" }
  ]
}

생성되는 스키마:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "meta": {
      "type": "object",
      "properties": {
        "same_name": {
          "type": "object",
          "properties": {
            "region": { "type": "array", "items": {} },
            "keyword": { "type": "string" },
            "selected_region": { "type": "string" }
          },
          "required": ["region", "keyword", "selected_region"]
        },
        "pageable_count": { "type": "integer" },
        "total_count": { "type": "integer" },
        "is_end": { "type": "boolean" }
      },
      "required": ["same_name", "pageable_count", "total_count", "is_end"]
    },
    "documents": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "place_name": { "type": "string" },
          "distance": { "type": "string" },
          "phone": { "type": "string" },
          "x": { "type": "string" },
          "y": { "type": "string" }
        },
        "required": ["place_name", "distance", "phone", "x", "y"]
      }
    }
  },
  "required": ["meta", "documents"]
}

좌표 x, y와 거리 distance는 숫자처럼 보이지만 응답에서 문자열이라 string이 됩니다. 문서의 카테고리로 장소 검색 예제는 "same_name": null을 돌려주므로, 이 스키마로 검사하면 same_name이 객체가 아니어서 통과하지 못합니다. 두 API 응답을 한 스키마로 검사하려면 둘을 배열로 묶어 다시 생성한 뒤 items를 쓰세요.

다음은 좌표로 행정구역정보 변환 응답입니다. 여기서는 x, y가 숫자입니다.

{
  "meta": { "total_count": 2 },
  "documents": [
    { "region_type": "B", "code": "4113510900", "x": 127.10459896729914, "y": 37.40269721785548 },
    { "region_type": "H", "code": "4113565500", "x": 127.1163593869371, "y": 37.40612091848614 }
  ]
}
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "meta": { "type": "object", "properties": { "total_count": { "type": "integer" } }, "required": ["total_count"] },
    "documents": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "region_type": { "type": "string" },
          "code": { "type": "string" },
          "x": { "type": "number" },
          "y": { "type": "number" }
        },
        "required": ["region_type", "code", "x", "y"]
      }
    }
  },
  "required": ["meta", "documents"]
}

이 스키마는 x가 "127.10459896729914"처럼 문자열이면 거부합니다. 스키마는 넣은 샘플만 보고 만들어집니다. 한 스키마로 여러 API를 검사하려면 각 응답을 배열로 묶어 생성하고 items를 쓰세요. 이 응답과 앞의 키워드 검색 응답을 묶으면 x, y는 ["string", "number"]가 됩니다. 그렇지 않으면 API마다 따로 생성하세요. 예제의 code는 10자리 문자열이지만, 생성된 스키마는 자릿수를 검사하지 않습니다.

Ajv로 검증하기

Ajv 8은 기본 Ajv 클래스로 draft-07을 검증합니다. format 키워드에는 ajv-formats가 필요하며, 없으면 compile()이 unknown format "email"을 던집니다.

import Ajv from 'ajv';
import addFormats from 'ajv-formats';

const ajv = new Ajv();
addFormats(ajv);

const validate = ajv.compile({
  type: 'object',
  properties: {
    email: { type: 'string', format: 'email' },
    coupon: { type: ['string', 'null'] },
  },
  required: ['email'],
  additionalProperties: false,
});

validate({ email: 'a@example.com', extra: 1 }); // false: must NOT have additional properties

생성기는 format, minimum, maxLength, pattern, enum, additionalProperties: false를 넣지 않습니다. 데이터가 지켜야 할 규칙에 맞게 추가하세요.

제한 사항

  • 배열 요소는 병합합니다. [{"id": 1, "name": "Alice"}, {"id": 2, "email": "b@example.com"}]이면 items에 id, name, email이 들어가고, 필수는 모든 요소에 있는 id뿐입니다. 같은 배열의 정수와 소수는 "number"가 됩니다. 생성된 스키마는 원래 샘플을 항상 통과시킵니다. GenSON도 같은 방식으로 샘플을 병합합니다.
  • 필수 항목은 샘플에서 정해집니다. 객체 하나에서는 null이 아닌 키가 모두 required에 들어갑니다. 데이터에서는 선택이지만 샘플에 있는 필드는 직접 required에서 빼세요.
  • 타입이 섞이면 타입 목록이 됩니다. [1, "x", {"a": 1}] 같은 배열은 "type": ["integer", "string", "object"]가 되고 옆에 객체의 properties와 required가 붙습니다. 이 두 키워드는 객체 요소에만 적용됩니다.
  • draft-07만 출력합니다. 2020-12를 쓰려면 $schema를 바꾸고 Ajv의 Ajv2020 클래스를 사용하세요.

FAQ

어떤 버전의 JSON Schema를 생성합니까?

널리 지원되는 JSON Schema draft-07을 생성합니다. AJV, jsonschema(Python) 등 주요 검증기와 호환되며 ZeroTool의 JSON Schema 검증기에서도 그대로 쓸 수 있습니다.

필수 필드는 어떻게 결정됩니까?

입력 JSON 객체의 null이 아닌 모든 속성이 required 배열에 추가됩니다. null 값은 값이 있다고 보장할 수 없어 제외됩니다. 객체 배열에서는 모든 객체에 null이 아닌 값으로 있는 키만 필수입니다. 출력 스키마를 편집하여 required 목록을 조정할 수 있습니다.

중첩 객체와 배열을 지원합니까?

지원합니다. 중첩 객체와 배열을 재귀적으로 처리합니다. 배열의 items 스키마는 모든 요소를 병합해 만들어 어떤 요소든 통과하고, 중첩 객체는 properties와 required 배열을 생성합니다.

생성한 스키마를 바로 검증에 쓸 수 있나요?

네. 생성한 스키마를 ZeroTool의 JSON Schema 검증기나 Ajv 기반 검증기에 붙여 넣으면 됩니다. 선택 필드를 required에서 빼거나 minLength, minimum, pattern 같은 제약을 추가해야 할 수 있습니다.

JSON이 서버로 전송됩니까?

아니요. 스키마는 입력할 때마다 브라우저 탭 안에서 생성되며, 입력한 JSON을 서버로 보내거나 브라우저 저장소에 저장하지 않습니다. 입력란 편집을 마쳤을 때와 스키마를 복사할 때 페이지의 방문 통계에 사용 이벤트(도구 이름과 convert 또는 copy라는 동작) 1건만 기록되며 JSON이나 스키마 내용은 포함되지 않습니다.

카카오 로컬 API 응답에서 x, y가 string일 때와 number일 때가 있는 이유는 무엇인가요?

도구는 값의 모양이 아니라 JSON 타입을 봅니다. 키워드로 장소 검색 응답의 x, y는 "127.05902969025047"처럼 따옴표로 감싼 문자열이라 string이 되고, 좌표로 행정구역정보 변환 응답의 x, y는 따옴표 없는 숫자라 number가 됩니다. 두 응답을 배열로 묶어 생성하면 items 안의 x, y는 ["string", "number"]가 됩니다.