JSON Schema

우동이·2022년 3월 22일
3

JSON Schema

목록 보기
1/2
post-thumbnail

1. JSON Schema?

  • Key와 Value로 이루어진 JSON Data를 정해진 규칙으로 구성되었는지 유효성 검사를 제공합니다.
    • 검사하는 규칙을 의미
  • 검증 과정 => 아래의 기준을 키워드를 이용해 명시할 수 있습니다.
    • 데이터의 타입이 정확한가?
    • 필수로 받아와야 하는 데이터를 포함하는가?
    • 데이터가 원하는 범위안에 속하는가?
  • 참고자료

2. 키워드

  • 메타 키워드
    • 유효성 검사에서는 제외되지만 스키마의 기본 정보를 표현할 수 있습니다.
키워드의미
title스키마의 이름
description스키마의 설명
example스키마 검증에 통과하는 예시 ( 배열 형태 )
$comment스키마의 주석
  • 예시
{
    "title": "우동이의 스키마",
    "description": "이 스키마는 우동이의 스키마 입니다.",
    "example": ["woo", "dong"],
    "$comment": "이 스키마는 매우 중요해!",
   ...
}
  • 검증 키워드
    • JSON 데이터를 검증하는데 사용되는 키워드 입니다.
키워드의미
type유효한 데이터 타입을 명시
required필수 속성을 배열 형태로 표현
properties객체 타입인 경우 속성을 표시
minLength문자열의 최소 길이
maxLength문자열의 최대 길이
minItems배열 요소의 최소 개수
maxItems배열 요소의 최대 개수
minimum최소값 이상의 숫자만 유효
maximum최댓값 이하의 숫자만 유효
multipleOf명시한 숫자의 배수만 유효
pattern정규 표현식과 일치한 문자열만 유효
  • 데이터 타입
    • JSOM Data와 다른점은 숫자 타입이 2개 존재한다는 점 입니다.
키워드의미
number모든 숫자
integer정수
string문자열
booleantrue / false
objectKey / Value 형태
array배열
null값이 존재하지 않음

3. 스키마 선언과 검증하기

3-1 숫자

  • 숫자 검증
    • 해당 데이터가 숫자인지 검사합니다.
    • 정수뿐만 아니라 실수까지 모두 검증을 통과합니다.
{
	"type": "number"
}
  • 정수 검증
    • 해당 데이터가 정수인지 검사합니다.
{
	"type": "integer"
}
  • 배수 검증
    • multipleOf 키워드를 이용해 해당 숫자가 명시된 숫자의 배수인지 검사합니다.
// 해당 데이터가 숫자이면서 3의 배수인지 검사
{
	"type": "number",
  "multipleOf": 3
}
  • 범위 검증
    • 아래의 키워드를 활용해서 해당 숫자가 유효한 범위를 가지는지 검사합니다.
      • minimum: 최솟값 이상
      • maximum: 최댓값 이하
      • exclusiveMinimum: 불리언 값을 명시하며 minimum키워드로 명시한 값을 포함해서 검사할지 결정합니다.
      • exclusiveMaximum: 불리언 값을 명시하며 `maximum키워드로 명시한 값을 포함해서 검사할지 결정합니다.
// 해당 데이터가 숫자이고 1보다 크거나 같고 10보다는 작은 숫자인지 검사 => 5>n>=1
{
    "type": "number",
    "minimum": 1,
    "maximum": 5,
    "exclusiveMaximum": true // default: false
}

3-2 문자열

  • 문자열 검사
    • 해당 데이터가 문자열인지 검사합니다.
{
    "type": "string"
}
  • 문자열 길이 검사
    • 해당 데이터가 문자열인지 검증하고 길이가 5보다 크고 7보다 작은지 검사합니다.
{
    "type": "string",
    "minLength": 5,
    "maxLength": 7
}
  • 정규 표현식 검사
    • pattern키워드를 사용하여 명시한 정규 표현식과 일치하는지 검사합니다.
// 해당 데이터가 문자열이고 1개 이상의 영문 소문자를 가지는 문자열인지 검사
{
    "type": "string",
    "pattern": "[a-z]+"
}
  • 문자열 포맷 검사
    • 해당 데이터가 지정한 포맷인지 검사합니다.
    • 예시
      • date-time: 1993-01-01T00:00:00+09:00
      • time: 00:00:00+09:00
      • date`: 1993-01-01
      • email: woodong@naver.com
      • hostname: woodong.com
// 문자열이고 날짜인지 검사
{
    "type": "string",
    "format": "date"
}
  • 이외에 다른 타입 검증도 존재

3-3 객체 검증

  • 객체 타입 검증
    • 해당 데이터가 객체인지 검사합니다.
{
    "type": "object"
}
  • 프로퍼티 검증
    • 객체의 프로퍼티가 유효한지 검사합니다.
{
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"},
    }
}
  • 필수 프로퍼티 검증
    • required 키워드를 사용해 필수 프로퍼티를 검증합니다.
    • 배열 형태로 이름을 나열합니다.
{
    "type": "object",
    "properties": {
        "name": {"type": "string"},
        "age": {"type": "integer"},
    },
    "required": ["name", "age"]
}
  • 프로퍼티 개수 검증
    • minProperties / maxProperties 키워드를 활용해 객체가 가질 수 있는 프로퍼티 개수의 최솟값 / 최댓값을 검증합니다.
// 해당 데이터는 객체이며 프로퍼티를 1개 이상 2개 이하를 가져야 합니다.
{
    "type": "object",
    "minProperties": 1,
    "maxProperties": 4
}
  • 프로퍼티 이름 검증
    • pattern 키워드를 이용해 객체가 갖는 프로퍼티 이름을 검증할 수 있습니다.
// 검사하는 객체는 반드시 프로퍼티의 이름이 a, b로 시작해야 합니다.
{
    "type": "object",
    "propertyNames": {
        "pattern": "^[a-b].+"
    }
}
  • 프로퍼티 의존성 검증
    • dependencies 키워드를 활용해 프로퍼티 간의 의존성을 설정할 수 있습니다.
// age 프로퍼티는 name 프로퍼티에 의존합니다 => name 프로퍼티 없이 age 프로퍼티만 있으면 안됩니다.
// 둘다 없는 것은 가능합니다.
{
    "type": "object",
    "properties": {
        "name": {
            "type": "string"
        },
        "email": {
            "type": "string"
        },
        "age": {
            "type": "integer"
        }
    },
    "dependencies": {
        "age": ["name"]
    }
}

// 통과하지 못하는 데이터
{
    "email": "woodong@naver.com",
    "age": 28
}
  • 스키마 의존성 검증
    • dependencies 키워드를 활용해 스키마 간의 의존성을 설정할 수 있습니다.
// 이 데이터는 name or email 프로퍼티를 가진 객체를 정의하되 name 프로퍼티가 존재한다면 반드시 정수형의 age 프로퍼티가 있어야 검증을 통과합니다.
{
    "type": "object",
    "properties": {
        "name": {
            "type": "string"
        },
        "email": {
            "type": "string"
        }
    },
    "dependencies": {
        "name": {
            "properties": {
                "age": {
                    "type": "integer"
                }
            },
            "required": [
                "age"
            ]
        }
    }
}

// 검증 실패 케이스
{
  "name": "woodong",
  "email": "wooodng@naver.com"
}

{
  "name": "woodong",
  "email": "wooodng@naver.com",
  "age": '28' // 정수형이 아닙니다.
}

// 검증 통과 케이스
{
  "email": "wooodng@naver.com",
  "age": '28' // 정수형이 아니어도 통과
}

3-4 배열 검증

  • 배열 검증
    • 해당 데이터가 배열인지 검증합니다.
{
    "type": "array"
}
  • 배열 요소 검증
    • item 키워드를 이용해 배열에 저장된 요소를 검증합니다.
// 배열의 요소가 모두 정수이거나 비어있으면 통과
{
    "type": "array",
    "items": {
        "type": "integer"
    }
}

// 배열의 요소를 다른 JSON 스키마로 검사할 수 있습니다.
// 통과 데이터: ["abc", d, 5], ["abc", d, 5, ...]
{
    "type": "array",
    "items": [
        {
            "type": "string",
            "maxLength": 5
        },
        {
            "type": "string"
        },
        {
            "type": "number"
        }
    ]
}

// additionalItems 키워드를 활용해 추가 요소 검증
// 통과 데이터: ["abc"]
{
    "type": "array",
    "items": [
        {
            "type": "string",
            "maxLength": 5
        },
    ],
    "additionalItems": false
}
  • 배열 길이 검증
    • minItems / maxItems 키워드를 활용해 배열이 가질 수 있는 길이의 최솟값 / 최댓값을 검증합니다.
// 배열의 요소 5~10개 검사
{
    "type": "array",
    "minItems": 5,
    "maxItems": 10
}
  • 중복 값 검증
  • uniqueItems 키워드를 활용해 해당 배열에 저장된 요소의 중복값을 검증합니다.
    • true: 중복 값 비허용
{
    "type": "array",
    "uniqueItems": true
}

3-5 기타 검증

  • boolean 검증
    • 해당 데이터가 booelan 인지 검증합니다.
    • true / false 대신에 숫자 1과 0을 사용할 수 없습니다.
{
    "type": "boolean"
}
  • null 검증
    • 해당 데이터가 null 인지 검사합니다.
{
    "type": "null"
}
  • 열거형 데이터 검증
    • enum 키워드를 사용해 해당 데이터가 명시된 배열에 속하는지 검증합니다.
    • 중복 값을 허용하지 않습니다.
// 해당 문자열이 김밥 / 라면 / 우동 이외에 다른 문자열은 통과할 수 없습니다.
{
    "type": "string",
    "enum": ["김밥", "라면", "우동"]
}
  • 상수값을 이용한 검증
    • constant 키워드를 사용하여 해당 프로퍼티의 값을 검증합니다.
// 이 객체의 name 프로퍼티는 반드시 woodong 문자열을 가져야 검증을 통과합니다.
{
    "properties": {
        "name": {
            "const": "woodong"
        }
    }
}

4. 스키마 결합

  • 여러 키워드를 활용해 스키마를 결합할 수 있습니다.
  • allOf
    • 명시된 배열에 나열된 모든 JSON 스키마를 한 번에 검증할 수 있습니다.
    • 나열된 모든 스키마에 대한 검증을 통과해야 합니다.
// 문자열의 길이가 최소 3이상 검증 스키마와 문자열의 길이가 최소 5 이하 검증 스키마를 동시에 검증
// 문자열의 길이는 3 이상 5 이하만 가능
{
    "allOf": [
        {"minLength": 1},
        {"maxLength": 5}
    ]
}
  • anyOf
    • 나열된 스키마 중 하나 이상의 스키마에 대한 검증만 통과하면 됩니다.
// 문자열 or 숫자일 경우 통과
{
    "anyOf": [
        {"type": "string"},
        {"type": "number"}
    ]
}
  • oneOf
    • 나열된 스키마 중 오직 하나의 스키마에 대한 검증만 통과하면 됩니다.
// 해당 데이터가 숫자이면서도 2의 배수 or 5의 배수면 통과
// 10( 2와 5의 공배수 )은 통과할 수 없습니다.
{
    "oneOf": [
        { "type": "number", "multipleOf": 2 },
        { "type": "number", "multipleOf": 5 }
    ]
}

5. 스키마 조건

  • not
    • 명시된 스키마를 만족하지 않는 데이터를 검증할 수 있습니다.
// 해당 데이터는 문자열이 아닌 데이터만 통과합니다.
{
    "not": {
        "type": "string"
    }
}
  • if-then-else
    • if 만족 => then 실행
    • if 불만족 => else 실행
// 어느 데이터가 문자열이면 최소 5글자 이상이고 문자열이 아니면 데이터 타입이 null
{
  "if": {
    "type": "string"
  },
  "then": {
    "minLength": 5,
  },
  "else": {
    "const": null
  }
}

6. 스키마 재사용성

  • $id 키워드를 이용해 JSON 스키마에 고유한 값을 부여할 수 있습니다.
    • 고유한 식별자로 선언
    • 보통 최상위에 스키마 다운로드 위치를 선언
{
    "$id": "http://naver.com/woodong.json",

    "type": "string",
    "format": "email",
}
  • $ref 키워드를 이용해 JSOM 스키마 URI를 선언
{
    "type": "object",
    "properties": {
        "name": {
            "type": "string",
        },
        "email": {
            "$ref": "http://naver.com/woodong.json"
        }
    }
}
  • definitions 키워드를 이용해 유효성 검사를 재사용할 수 있습니다.
{
   "type":"object",
   "properties":{
      "product":{
         "type":"array",
         "items":[{ "$ref":"#/definitions/contents" }]
      },
      "user":{
         "type":"array",
         "items":[{ "$ref":"#/definitions/contents" }]
      },
   },
   "definitions":{
      "contents":{
         "type":"object",
         "properties":{
            "id":{ "type":"string" },
            "name":{ "type":"string" }
         }
      },
   }
}
profile
아직 나는 취해있을 수 없다...

0개의 댓글