How to strip optional null fields from json before processing
- Step 1Capture the full update object as a file — Save the candidate update — all possible fields, with unset optionals as null — to a
.jsonfile. For example{"name":"Ada","email":null,"bio":"Engineer","phone":null}. It must be a single valid JSON document. - Step 2Drop the file — Drag it onto the dropzone. The dropzone is file-only; there is no paste box, so save the object first.
- Step 3Strip null to build the PATCH body — Leave
null valuesticked (default). Do NOT tick targets for values you intend to send deliberately — if you mean to clear a field with""or[], leave those checkboxes off so they survive. - Step 4Decide on Deep for nested updates — Keep Deep on if you're updating a nested resource and want its optional nulls removed too. Turn it off if you only want to clean the top-level update keys.
- Step 5Run and inspect the payload — Click Strip Values. The result is your PATCH-safe body: only fields with actual new values. The 'N values stripped' counter shows how many would-be overwrites you avoided.
- Step 6Use it as a fixture and port to the client — Copy the stripped payload as a test case for the endpoint, then implement the rule in your API client (
v != nullfilter) or rely on Prisma's?? undefinedpattern. Verify the endpoint changes only the provided fields.
How update systems read null vs absent
Stripping optional nulls produces the 'absent' payload these systems expect for 'leave unchanged'.
| System | Missing field means | null field means | Strip nulls? |
|---|---|---|---|
| JSON Merge Patch (RFC 7396) | Leave unchanged | Delete the member | Yes — unless you mean to delete |
| Prisma update() | Use undefined to skip | Set column to NULL | Yes — or convert null to undefined |
| Many REST PATCH endpoints | Leave unchanged | Often 'clear this field' | Yes — unless clearing is intended |
| GraphQL input (nullable arg) | Not provided | Explicitly null | Yes — to express 'not provided' |
| PUT (full replace) | Field removed from resource | Field set to null | Depends — PUT replaces wholesale |
When to strip and when to keep a value
The decision is about intent, not type. Keep deliberate signals out of the strip set.
| Field in the update | Intent | Action |
|---|---|---|
"phone": null (never entered) | Don't change phone | Strip — leave it out |
"avatarUrl": null (user removed photo) | Clear the avatar | Keep — don't tick null, or send separately |
"verified": false | Set verified to false | Keep — false is preserved automatically |
"bio": "" (user cleared bio) | Set bio to empty | Keep — leave empty strings unticked |
"tags": [] (user removed all tags) | Set tags to empty list | Keep — leave empty arrays unticked |
File and tier limits
Pro tool. From lib/tier-limits.ts and lib/csv-utils.ts.
| Limit | Free | Pro |
|---|---|---|
| Max file size | 2 MB | 100 MB |
| Files per run | 1 | Up to 10 |
| Accepted extensions | .json .ndjson .jsonl .txt | .json .ndjson .jsonl .txt |
| Runs in | Browser | Browser |
Cookbook
Partial-update payloads before and after stripping. Field names are illustrative.
Build a PATCH-safe body
ExampleA profile edit form sends all fields; only name and bio changed. Stripping null yields a body that won't wipe email or phone.
Input (update.json):
{
"name": "Ada",
"email": null,
"phone": null,
"bio": "Engineer"
}
Strip Values (targets: null · Deep on):
{
"name": "Ada",
"bio": "Engineer"
}
2 would-be overwrites avoided.Keep a deliberate clear
ExampleThe user removed their avatar, which IS the change. Don't tick null so avatarUrl stays in the body as an explicit clear.
Input:
{ "avatarUrl": null, "theme": null, "name": "Ada" }
Strip Values (targets: empty strings only · null UNCHECKED):
{ "avatarUrl": null, "theme": null, "name": "Ada" }
Both nulls survive because null wasn't a target.
Send avatarUrl:null deliberately; handle theme separately.Set a boolean to false
ExampleTurning off a flag must reach the server. false is never stripped, so it stays in the PATCH body alongside the cleaned nulls.
Input:
{ "verified": false, "middleName": null }
Strip Values (targets: null · Deep on):
{ "verified": false }
The false update is preserved; the unset middleName is dropped.Minimise a nested resource update
ExampleUpdating a nested settings object; Deep mode strips its optional nulls too so the nested PATCH is also minimal.
Input:
{
"id": 5,
"settings": { "locale": "en", "timezone": null }
}
Strip Values (targets: null · Deep on):
{
"id": 5,
"settings": { "locale": "en" }
}Prisma: null to undefined pattern
ExampleIf your stack is Prisma, convert null to undefined so the field is skipped rather than nulled — the code mirror of stripping.
// After stripping or in the client:
await prisma.user.update({
where: { id },
data: {
name: updates.name,
email: updates.email ?? undefined // null -> skip
}
});Errors and edge cases
Real errors and silent failures sourced from each platform's own documentation. Match the wording to the row, fix what the row says to fix.
null means 'clear this field' in a PATCH
CautionUnder JSON Merge Patch and many PATCH endpoints, an explicit null deletes/clears the field. If that's your intent, do NOT strip it — leave the null checkbox off, or send the clearing field in a separate request.
false update preserved
PreservedSetting a flag to false is a real change and is never stripped. The body keeps "verified": false so the server applies it. There's no falsy mode that could drop it.
Empty string / empty array as a deliberate set
Caution"bio": "" (clear bio) or "tags": [] (remove all tags) are real updates. Leave empty strings / empty arrays unticked so they survive into the PATCH body.
Prisma needs undefined, not absent-in-JSON
By designStripping produces an object without the key. Prisma's update wants undefined for 'skip', which JSON can't represent. Convert null to undefined in code (?? undefined) — stripping models the intent but the runtime fix is the JS side.
PUT vs PATCH semantics
CautionPUT replaces the whole resource, so a stripped field may be interpreted as 'removed' rather than 'unchanged'. Only strip for PATCH/merge-patch style partial updates, not full-replace PUTs.
Invalid JSON in the update file
Parse errorA trailing comma or BOM throws on parse and the run fails. Fix the file with json-format-fixer before stripping.
Deep off leaves nested optional nulls
ExpectedWith Deep unchecked, nested objects keep their nulls. For a nested partial update, turn Deep on so the nested resource is also minimised.
undefined checkbox on a file
By designIt's a no-op — JSON files can't contain undefined. Use null here and handle undefined in your application code.
File over the size limit
BlockedFree caps at 2 MB, Pro at 100 MB. Update payloads are tiny, so this rarely applies — but a bulk array of updates could hit it.
Need to remove keys by name, not by value
Wrong toolIf you want to drop or keep specific keys regardless of value (e.g. always exclude internalId), use json-key-filter instead of value-based stripping.
Frequently asked questions
Why strip optional nulls before a PATCH?
Because many update systems read a present null as 'clear this field'. A form that nulls every untouched optional and PATCHes the whole object will wipe data the user never edited. Stripping leaves only fields with real new values, so the update changes exactly what was intended.
When should I keep null in the payload?
When null is the change — e.g. clearing an avatar ({"avatarUrl": null}) under JSON Merge Patch. Leave the null checkbox off for those, or send the clear as a separate explicit request.
How does Prisma treat null vs undefined?
Prisma reads undefined as 'skip this field' and null as 'set the column to NULL'. To leave a field unchanged, pass undefined — commonly updates.email ?? undefined, which converts a null into a skip. Stripping models this; the runtime conversion happens in your code.
Will it remove a false I want to send?
No. false and 0 are real values and are never stripped, so a 'set verified to false' or 'set count to 0' update stays in the body.
Is the record/update data uploaded?
No. The file is read and stripped entirely in your browser. Record and update payloads never reach JAD Apps servers.
Can I paste the object instead of uploading a file?
No — the tool is file-only. Save the update object to a .json file and drop it. There's no paste textarea.
Does it handle nested partial updates?
Yes, with Deep on (default). Nested objects are recursed so a nested resource's optional nulls are removed too. Turn Deep off to clean only the top-level keys.
Is this safe for a PUT request?
Be careful. PUT replaces the whole resource, so a stripped (absent) field may be treated as removed rather than unchanged. Strip for PATCH/merge-patch semantics; for PUT, send the full intended representation.
How do I verify the endpoint behaved correctly?
Use the stripped payload as a test fixture, send it, then read the resource back and diff it against the expected state with json-diff to confirm only the provided fields changed.
What if I want to drop fields by name instead?
Value-based stripping won't do that. Use json-key-filter to include or exclude specific keys regardless of their value.
What about empty strings or empty arrays I want to send?
Leave empty strings and empty arrays unticked. They're off by default, so a deliberate "" (clear text) or [] (remove all items) survives into the payload while nulls are stripped.
Is there a limit on payload size?
Yes — 2 MB on Free, 100 MB on Pro. Single update bodies are tiny; only a large batch array would approach the limit.
Privacy first
Conversion runs locally in your browser. No file is uploaded — only metadata counters are saved for signed-in dashboard stats.