Form field map
form-field-map · version 1.0.0 · Forms · free, no key needed
Rename form fields with an explicit id map and reject collisions.
Use when you need to: map form field ids · migrate form fields.
Supported
- map form field ids
- migrate form fields
Not supported
- inferred renames
- transitive closure
- fuzzy matching
- silent collision merge
Behavior
- mapping rows are explicit {from, to} pairs. from must be a current field id. The step is not applied transitively.
- unmapped is required and is keep or drop. Identity mappings are allowed.
- Two sources for one target, or a kept field that already uses the target id, throw a collision naming the target and sources.
- Dropped answers are echoed on the dropped row. Unknown answer keys throw instead of being dropped.
- Output field order follows the original order. Prototype-named ids stay ordinary own keys.
Input
definition(object, required)answers(object, optional)mapping(array of object, required)unmapped(one of "keep", "drop", required)
Output
definition(object, required)answers(object, optional)renamed(array of any, required)dropped(array of any, required)unchanged_ids(array of string, required)counts(object, required)
Limits
- max input bytes: 262144
- max output bytes: 262144
- max input depth: 16
- max input nodes: 20000
- max fields: 100
- max choices: 50
- max respondents: 100
- max id bytes: 128
- max label bytes: 256
- max choice bytes: 128
- max answer string bytes: 4096
- max answer depth: 6
- max answer nodes: 50
- max changes: 500
- max mapping: 100
Example
Request input:
{
"definition": {
"fields": [
{
"id": "email",
"label": "Email",
"type": "string",
"required": true
},
{
"id": "name",
"label": "Name",
"type": "string",
"required": false
}
]
},
"answers": {
"email": "a@b.test",
"name": "Ada"
},
"mapping": [
{
"from": "email",
"to": "email_address"
}
],
"unmapped": "keep"
}
Response:
{
"result": {
"definition": {
"fields": [
{
"id": "email_address",
"label": "Email",
"type": "string",
"required": true
},
{
"id": "name",
"label": "Name",
"type": "string",
"required": false
}
]
},
"answers": {
"email_address": "a@b.test",
"name": "Ada"
},
"renamed": [
{
"from": "email",
"to": "email_address"
}
],
"dropped": [],
"unchanged_ids": [
"name"
],
"counts": {
"fields_in": 2,
"fields_out": 2,
"renamed": 1,
"dropped": 0,
"unchanged_ids": 1,
"answers_moved": 1,
"answers_dropped": 0,
"answers_kept": 1
}
}
}
How to call it
MCP
Connect https://computefirst.net/mcp (setup), then call execute with:
{
"id": "form-field-map",
"version": "1.0.0",
"input": {
"definition": {
"fields": [
{
"id": "email",
"label": "Email",
"type": "string",
"required": true
},
{
"id": "name",
"label": "Name",
"type": "string",
"required": false
}
]
},
"answers": {
"email": "a@b.test",
"name": "Ada"
},
"mapping": [
{
"from": "email",
"to": "email_address"
}
],
"unmapped": "keep"
}
}
HTTP (no key)
curl -X POST https://computefirst.net/v1/tools/form-field-map/versions/1.0.0/execute \
-H "Content-Type: application/json" \
-d '{"definition":{"fields":[{"id":"email","label":"Email","type":"string","required":true},{"id":"name","label":"Name","type":"string","required":false}]},"answers":{"email":"a@b.test","name":"Ada"},"mapping":[{"from":"email","to":"email_address"}],"unmapped":"keep"}'
The machine-readable contract is at /v1/tools/form-field-map/versions/1.0.0.
CLI
node cli.mjs run form-field-map 1.0.0 --input input.json --base-url https://computefirst.net
Get the client at /clients/cli/.
Related tools
- Form definition diff: Diff two form definitions by stable field id, including choice lists and field order.
- Form answer diff: Diff two answer maps against one shared form definition.
- Form compare: Compare two filled form snapshots and return compact field and answer changes.
- Form response check: Report missing required answers, nulls, type failures, and choice failures.
- Form response diff: Reconcile two form response sets by exact respondent id.