숏컷 코드
{
"type": "object",
"patternProperties": {
"^S_": { "type": "string" },
"^I_": { "type": "integer" }
},
"additionalProperties": false
}동적 key 검증
properties는 고정 이름, patternProperties는 이름 패턴에 맞다
JSON object의 key가 항상 정해져 있으면 properties가 가장 읽기 쉽습니다. 하지만 locale map, metric map, prefixed key처럼 key 이름이 데이터에 따라 달라지는 구조라면 patternProperties가 필요합니다. patternProperties는 property name이 정규식과 맞을 때 해당 value schema를 적용합니다.
{
"type": "object",
"patternProperties": {
"^[a-z]{2}-[A-Z]{2}$": { "type": "string" }
},
"additionalProperties": false
}이 구조는 "ko-KR": "안녕하세요", "en-US": "Hello" 같은 locale key를 검증하기 좋습니다.
정규식은 anchor를 붙이지 않으면 부분 매칭된다
patternProperties의 정규식은 이름 전체가 아니라 일부에 매칭될 수 있습니다. 예를 들어 "p"는 "p"뿐 아니라 "apple"에도 맞을 수 있습니다. 그래서 key 전체를 제한하려면 ^...$ 형태로 anchor를 붙이는 편이 안전합니다. prefix 정책이면 "^x-", 전체 형식이면 "^[a-z0-9_-]+$"처럼 의도를 명확히 나눕니다.
{
"patternProperties": {
"id": { "type": "string" }
}
}위 schema는 "id"뿐 아니라 "user_id", "identity"까지 매칭될 수 있습니다. 전체 key를 제한하려면 "^id$"가 맞습니다.
additionalProperties와 함께 써야 닫힌 map이 된다
patternProperties만 쓰면 패턴에 맞지 않는 key가 기본적으로 허용될 수 있습니다. 특정 패턴의 key만 허용하려면 additionalProperties: false를 같이 써야 합니다. 반대로 패턴 key와 일반 key를 함께 허용해야 한다면 properties, patternProperties, additionalProperties의 책임을 나눠야 합니다.
언제 무엇을 쓸까
| 상황 | 적합한 선택 |
|---|---|
| 필드 이름이 고정됨 | properties |
| key가 prefix나 정규식 규칙을 가짐 | patternProperties |
| key 이름 자체의 형식만 제한 | propertyNames |
| 패턴 밖의 key를 막음 | additionalProperties: false |
| 확장 필드를 허용하되 value 타입만 제한 | additionalProperties에 schema 지정 |
주의할 점
patternProperties 정규식은 anchor 없이 쓰면 예상보다 넓게 매칭될 수 있습니다.
동적 key를 검증할 때는 key 전체를 볼지, prefix만 볼지 먼저 정하고 정규식을 작성해야 합니다.
{
"patternProperties": {
"S_": { "type": "string" }
}
}이 패턴은 "S_name"뿐 아니라 "user_S_name"도 매칭될 수 있습니다. prefix만 허용하려면 "^S_", 전체 형식이면 "^S_[A-Za-z0-9_]+$"처럼 고정합니다.
참고 링크
1 sources