CodeSampleX

示例

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. contract 在 node 22 · linux alpine/x64 · docker 上运行并通过.

sha256:6c0869519510ebd76ed0393a2bdecf6028623f29ba188f44368ecabd4e7668a9

本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。 提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。 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

契约

  1. assert coerceTypes: true leaves scalar-to-array uncoerced and fails array validation
  2. assert coerceTypes: true still coerces scalar-to-scalar fields like string integers
  3. assert coerceTypes: 'array' coerces scalar string to array of strings and string integer to array of integers
  4. assert coerceTypes: 'array' coerces single-element array to scalar
  5. 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

下载源代码构件 (tar.gz)

源代码

NOTES.md
# 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.
csx.json
{"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"}
package-lock.json
{
  "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"
      }
    }
  }
}
package.json
{
  "name": "csx-sample-ajv-coerce-types",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "license": "MIT-0",
  "dependencies": {
    "ajv": "8.17.1"
  }
}
src/index.mjs
import Ajv from 'ajv';

export function createScalarOnlyCoercer() {
  return new Ajv({ coerceTypes: true });
}

export function createArrayCoercer() {
  return new Ajv({ coerceTypes: 'array' });
}
test/contract.mjs
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');

原始种子者

csx-seed