Lập trình · 21/10/2026

JavaScript JSON.parse Reviver: Missing return Can Discard Your Data

Valid JSON produces undefined after adding an inspection callback. The JSON.parse reviver transforms values rather than merely observing them. Its return value determines what is retained, replaced or deleted.

JSON.parse reviver trong JavaScript: quên return có thể làm mất dữ liệu

Valid JSON produces undefined after adding an inspection callback. The JSON.parse reviver transforms values rather than merely observing them. Its return value determines what is retained, replaced or deleted.

1. Missing return can discard the entire result

const visited = [];
const result = JSON.parse('{"count":2}', (key, value) => {
  visited.push(key);
});
console.log(result === undefined); // true
console.log(JSON.stringify(visited)); // ["count",""]

A callback without return produces undefined. The reviver visits count and then the root under an empty key. Returning undefined at the root discards the entire result; the input JSON is not syntactically invalid.

2. Return value for fields that should remain

const result = JSON.parse('{"label":"ready","enabled":false}', (key, value) => {
  if (key === 'label' && typeof value === 'string') {
    return value.toUpperCase();
  }
  return value;
});
console.log(JSON.stringify(result)); // {"label":"READY","enabled":false}

The default return preserves unchanged values, including the root object. Avoid return value || undefined: it deletes valid false, zero and empty-string values too.

A name-based rule affects label properties at every depth. For a transformation limited to one schema path, parsing first and transforming explicitly may be clearer.

3. Deleting an array element leaves a hole

const result = JSON.parse('[1,2,3]', (key, value) => {
  if (value === 2) return undefined;
  return value;
});
console.log(result.length); // 3
console.log(Object.hasOwn(result, 1)); // false
console.log(JSON.stringify(result)); // [1,null,3]

The example demonstrates unchanged length and an absent indexed property. Reserializing expresses that hole as null; the in-memory result was not a replacement of 2 with null. Parse and filter deliberately when a shorter list is required.

4. Children are processed before parents

const order = [];
const result = JSON.parse('{"child":{"value":2}}', (key, value) => {
  order.push(key);
  if (key === 'value') return value * 10;
  if (key === 'child') console.log(value.value); // 20
  return value;
});
console.log(JSON.stringify(order)); // ["value","child",""]
console.log(result.child.value); // 20

The child callback receives the already transformed nested value. The final root visit uses ''. Actual JSON properties can also have empty names, so key === '' alone cannot identify the root for arbitrary data.

Parsing does not validate application schemas. Check required fields, types and allowed ranges after transformation. These small examples do not handle dates or special numeric formats.

5. Review a reviver before introducing it

  • Return value on every preservation path.
  • Check the root result as well as child fields.
  • Test false, zero, empty strings and null.
  • Inspect array length and holes.
  • Review same-named fields at different depths.
  • Validate the resulting schema.

All eight bilingual code blocks ran with Node.js, alongside falsy-preservation and root-visit checks. API integration and performance were not tested. References: MDN JSON.parse and ECMAScript JSON.parse.

Discussion

Comments 0

Sign in to comment

You need an account to join the discussion and reply to other readers.

Sign inRegister

No comments yet. Be the first to share your thoughts.