# JSON field projection v1

Save `json-project.mjs` beside `json-project-example.mjs` containing this example.
Run `node json-project-example.mjs` with Node 18+; no runtime dependencies or network.

```js
import assert from 'node:assert/strict';
import { projectJsonFields } from './json-project.mjs';
const input = JSON.stringify([
  { id: '001', note: 'line\nnext', private: 'omit me' },
  { id: '002', note: '', private: 'omit me too' },
]);
const result = projectJsonFields(input, 'note\nid');
assert.equal(result.records, 2);
assert.equal(result.fields, 2);
assert.deepEqual(JSON.parse(result.output), [
  { note: 'line\nnext', id: '001' },
  { note: '', id: '002' },
]);
assert.equal(result.output, '[{"note":"line\\nnext","id":"001"},{"note":"","id":"002"}]');
console.log('JSON field projection example passed.');
```

## Contract

`projectJsonFields(input, fieldsInput)` returns `{ output, records, fields }`.
Supply a nonempty JSON array of flat objects with string values only.
Supply exact selected field names, one per line, in the desired order. CRLF
separators normalize to LF; names are never trimmed. Empty names, empty lines,
duplicate names and more than 50 selected fields reject. Whitespace-only names
are literal names. Every selected field must be an own property in every record.

The entire input is validated, including unselected fields. Invalid JSON,
non-array roots, empty arrays, non-object records and field values that are
numbers, booleans, null, arrays or nested objects reject. A failure stops the
whole conversion; no records are silently dropped. Error messages do not echo
input values. The output is a compact JSON array with no terminal newline.

Exact string values and literal key spacing preserve leading zeros, spaces,
empty strings, formula text, Unicode and escaped tabs, CR and newlines.
Controls remain inside strings and are escaped in output. Formulas are not
evaluated. Special keys such as `__proto__`, `constructor` and `toString`
remain inert own properties. Output keys follow selection order except numeric
index-like keys, which follow standard JSON.stringify ordering. JSON.parse
resolves duplicate input object keys using the last value; earlier duplicate
values cannot be recovered. Validation applies after that resolution.

Limits: 100,000 input characters, 100,000 field-selection characters,
499 records, 50 fields per input object,
50 selected fields and 300,000 output characters, measured as JavaScript string
length. Lone Unicode surrogates are escaped by JSON.stringify and count toward
the output limit. This helper performs no file writes, requests or formula
evaluation. Native export plus a local script is an alternative; no measured
advantage or user demand is claimed.

## Source parity

Generated from the browser's exact `site/lib/json-project.ts` core with
`node scripts/build-json-project-source.mjs`; use `--check` to verify bytes.
Tests compare runtime results/errors at input/output bounds and execute this
example. A download is not evidence of independent local execution. Input and
output are not sent in analytics.

## License

MIT License

Copyright (c) 2026 QuasiLife

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
