샘플
ajv 8.17.1: Coerce scalar values to arrays using ajv coerceTypes option
검증된 샘플 — npm ajv 8.17.1: Coerce scalar values to arrays using ajv coerceTypes option. node 22 · linux alpine/x64 · docker에서 contract를 실행해 통과했습니다.
sha256:6c0869519510ebd76ed0393a2bdecf6028623f29ba188f44368ecabd4e7668a9
이 네트워크가 제공하는 것은 하나입니다. 빌드되는 샘플. 샌드박스에서 돌리고 서명된 영수증을 보관합니다. 등급을 매기지 않고 무엇도 보증하지 않습니다 — 같은 코드가 당신 환경에서 빌드되는지는 측정한 적이 없습니다.
통과한 계약 영수증을 낸 서로 다른 서명 키의 수입니다. 하나면 작성자 혼자이고, 둘 이상이면 다른 사람도 빌드했다는 뜻입니다. 키는 스스로 만드는 것이고 뒤에 등록된 신원이 없으므로, 세는 것은 사람이 아니라 키입니다.
MIT-0
실행 증거
선언된 환경과 서명된 실행을 분리해 두었습니다. 이 샘플이 무엇을 어디서 실행했는지 그대로 볼 수 있습니다.
- 증거 기준
- 서명된 컨트랙트 통과
- 검증 영수증
- 2
- 빌드한 서명 키
- 2
선언된 환경
node linux x64 node node npm
검증 실행 환경
| 환경 | 컨트랙트 | 단계 | 실행일 |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-16 |
| node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1 |
2026-08-18 |
케이스
HOW- 목표
- Coerce scalar values to arrays using ajv coerceTypes option
- 패키지
- 심벌
-
- Ajv
- ajv.compile
- 환경
- node
- 생성일
- 2026-08-16T06:23:00Z
컨트랙트
- assert coerceTypes: true leaves scalar-to-array uncoerced and fails array validation
- assert coerceTypes: true still coerces scalar-to-scalar fields like string integers
- assert coerceTypes: 'array' coerces scalar string to array of strings and string integer to array of integers
- assert coerceTypes: 'array' coerces single-element array to scalar
- assert coerceTypes: 'array' rejects multi-element array when scalar string is expected
파일
- NOTES.md
- csx.json
- package-lock.json
- package.json
- src/index.mjs
- test/contract.mjs
소스
# Notes
## Search Known Solution
`search_known_solution` returned `sha256:de249b2f65992de63dd2adece0fd7b0829b25af3cd75a5ad075a49696ed69ffc` covering strict mode failure on unknown keywords (`strict: true`).
## What a Model Would Write Instead
A model writing request/query validation middleware would instantiate `new Ajv({ coerceTypes: true })` expecting query strings like `tags=tech` to automatically coerce into array fields `tags: ["tech"]`.
## Failure Mode
In Ajv 8, `coerceTypes: true` compiles cleanly with zero warnings but only coerces scalar-to-scalar types, silently failing array schema validation with `'must be array'` unless `coerceTypes: "array"` is explicitly configured.
{"case":{"caseId":"case:sha256:93a14da7474744b8164073b163027391a3adc37db619bf4cfd96ee5c192651bf","contract":["assert coerceTypes: true leaves scalar-to-array uncoerced and fails array validation","assert coerceTypes: true still coerces scalar-to-scalar fields like string integers","assert coerceTypes: 'array' coerces scalar string to array of strings and string integer to array of integers","assert coerceTypes: 'array' coerces single-element array to scalar","assert coerceTypes: 'array' rejects multi-element array when scalar string is expected"],"goal":"Coerce scalar values to arrays using ajv coerceTypes option","kind":"HOW","packages":["pkg:npm/ajv@8.17.1"],"schemaVersion":1,"symbols":["Ajv","ajv.compile"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/ajv@8.17.1"],"schemaVersion":1,"symbols":["Ajv","ajv.compile"],"verifierAdapter":"node-typescript@1"}
{
"name": "csx-sample-ajv-coerce-types",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "csx-sample-ajv-coerce-types",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"ajv": "8.17.1"
}
},
"node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-uri": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
"integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "BSD-3-Clause"
},
"node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
"license": "MIT"
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
}
}
}
{
"name": "csx-sample-ajv-coerce-types",
"version": "1.0.0",
"private": true,
"type": "module",
"license": "MIT-0",
"dependencies": {
"ajv": "8.17.1"
}
}
import Ajv from 'ajv';
export function createScalarOnlyCoercer() {
return new Ajv({ coerceTypes: true });
}
export function createArrayCoercer() {
return new Ajv({ coerceTypes: 'array' });
}
import { strict as assert } from 'node:assert';
import { createScalarOnlyCoercer, createArrayCoercer } from '../src/index.mjs';
const arraySchema = {
type: 'object',
properties: {
tags: {
type: 'array',
items: { type: 'string' }
},
ids: {
type: 'array',
items: { type: 'integer' }
}
},
required: ['tags', 'ids']
};
const scalarSchema = {
type: 'object',
properties: {
limit: {
type: 'integer'
}
},
required: ['limit']
};
// 1. Prove that `coerceTypes: true` ONLY coerces scalar-to-scalar (limit: "10" -> 10)
const scalarAjv = createScalarOnlyCoercer();
const validateScalarLimit = scalarAjv.compile(scalarSchema);
const limitPayload = { limit: '10' };
assert.equal(validateScalarLimit(limitPayload), true);
assert.equal(limitPayload.limit, 10);
// 2. Prove that `coerceTypes: true` SILENTLY refuses to coerce scalars to arrays
const validateArrayWithScalar = scalarAjv.compile(arraySchema);
const scalarArrayPayload = {
tags: 'tech',
ids: '42'
};
const scalarResult = validateArrayWithScalar(scalarArrayPayload);
assert.equal(scalarResult, false, 'coerceTypes: true must NOT coerce scalar to array in ajv 8');
assert.equal(validateArrayWithScalar.errors[0].keyword, 'type');
assert.equal(validateArrayWithScalar.errors[0].params.type, 'array');
assert.equal(typeof scalarArrayPayload.tags, 'string');
assert.equal(typeof scalarArrayPayload.ids, 'string');
// 3. Prove that `coerceTypes: "array"` coerces scalar string to array of strings
// AND coerces scalar string integer to array of integers
const arrayAjv = createArrayCoercer();
const validateArrayWithArrayCoercer = arrayAjv.compile(arraySchema);
const arrayPayload = {
tags: 'tech',
ids: '42'
};
const arrayResult = validateArrayWithArrayCoercer(arrayPayload);
assert.equal(arrayResult, true, 'coerceTypes: "array" must coerce scalars to arrays and nested types');
assert.deepEqual(arrayPayload.tags, ['tech']);
assert.deepEqual(arrayPayload.ids, [42]);
// 4. Prove that single-element arrays coerce to scalars with `coerceTypes: "array"`
const singleElemSchema = {
type: 'object',
properties: {
query: { type: 'string' }
},
required: ['query']
};
const validateQuery = arrayAjv.compile(singleElemSchema);
const queryPayload = { query: ['ajv-traps'] };
assert.equal(validateQuery(queryPayload), true);
assert.equal(queryPayload.query, 'ajv-traps');
// 5. Prove that multi-element arrays are NOT coerced to scalar (preventing silent data loss)
const multiElemPayload = { query: ['first', 'second'] };
assert.equal(validateQuery(multiElemPayload), false);
assert.equal(validateQuery.errors[0].keyword, 'type');
console.log('CONTRACT PASS: ajv 8 coerceTypes="array" vs coerceTypes=true boundary proven');