From dfaf34a863a88fa9260b71adddf832cd4c6aee47 Mon Sep 17 00:00:00 2001 From: Hakeem <65634467+Ahmed-Hakeem@users.noreply.github.com> Date: Tue, 12 Sep 2023 14:30:33 -0700 Subject: [PATCH] mention more details about reviver function (#29037) * mention last iteration of retreiver, and arrow function as a retriever * Linting the code to match the repo rules Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * add strict equality * Update files/en-us/web/javascript/reference/global_objects/json/parse/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update files/en-us/web/javascript/reference/global_objects/json/parse/index.md * fix linting * Update files/en-us/web/javascript/reference/global_objects/json/parse/index.md Co-authored-by: Joshua Chen * remove using of last iteration that's because we have no solid way of catching the last iteration * Update files/en-us/web/javascript/reference/global_objects/json/parse/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Apply suggestions from code linter Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Update files/en-us/web/javascript/reference/global_objects/json/parse/index.md Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Change the header to match the new example * Update files/en-us/web/javascript/reference/global_objects/json/parse/index.md Co-authored-by: Joshua Chen * change the header to be more descriptive Co-authored-by: Joshua Chen * change reviver example condition * stick with the old title --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Joshua Chen --- .../global_objects/json/parse/index.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/files/en-us/web/javascript/reference/global_objects/json/parse/index.md b/files/en-us/web/javascript/reference/global_objects/json/parse/index.md index f674a832d373f98..74641e1b41bf483 100644 --- a/files/en-us/web/javascript/reference/global_objects/json/parse/index.md +++ b/files/en-us/web/javascript/reference/global_objects/json/parse/index.md @@ -46,9 +46,21 @@ The {{jsxref("Object")}}, {{jsxref("Array")}}, string, number, boolean, or `null If a `reviver` is specified, the value computed by parsing is _transformed_ before being returned. Specifically, the computed value and all its properties (in a [depth-first](https://en.wikipedia.org/wiki/Depth-first_search) fashion, beginning with the most nested properties and proceeding to the original value itself) are individually run through the `reviver`. -The `reviver` is called with the object containing the property being processed as `this`, and two arguments: `key` and `value`, representing the property name as a string (even for arrays) and the property value. If the `reviver` function returns {{jsxref("undefined")}} (or returns no value — for example, if execution falls off the end of the function), the property is deleted from the object. Otherwise, the property is redefined to be the return value. If the `reviver` only transforms some values and not others, be certain to return all untransformed values as-is — otherwise, they will be deleted from the resulting object. +The `reviver` is called with the object containing the property being processed as `this` (unless you define the `reviver` as an arrow function, in which case there's no separate `this` binding) and two arguments: `key` and `value`, representing the property name as a string (even for arrays) and the property value. If the `reviver` function returns {{jsxref("undefined")}} (or returns no value — for example, if execution falls off the end of the function), the property is deleted from the object. Otherwise, the property is redefined to be the return value. If the `reviver` only transforms some values and not others, be certain to return all untransformed values as-is — otherwise, they will be deleted from the resulting object. -Similar to the `replacer` parameter of {{jsxref("JSON.stringify()")}}, `reviver` will be last called on the root object with an empty string as the `key` and the root object as the `value`. For JSON text parsing to primitive values, `reviver` will be called once. +Similar to the `replacer` parameter of {{jsxref("JSON.stringify()")}}, for arrays and objects, `reviver` will be last called on the root value with an empty string as the `key` and the root object as the `value`. For other valid JSON values, `reviver` works similarly and is called once with an empty string as the `key` and the value itself as the `value`. + +If you return another value from `reviver`, that value will completely replace the originally parsed value. This even applies to the root value. For example: + +```js +const transformedObj1 = JSON.parse('[1,5,{"s":1}]', (key, value) => { + return typeof value === "object" ? undefined : value; +}); + +console.log(transformedObj1); // undefined +``` + +There is no way to work around this generically. You cannot specially handle the case where `key` is an empty string, because JSON objects can also contain keys that are empty strings. You need to know very precisely what kind of transformation is needed for each key when implementing the reviver. Note that `reviver` is run after the value is parsed. So, for example, numbers in JSON text will have already been converted to JavaScript numbers, and may lose precision in the process. To transfer large numbers without loss of precision, serialize them as strings, and revive them to [BigInts](/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt), or other appropriate arbitrary precision formats. @@ -110,7 +122,7 @@ console.log(jsonText); // [[1,"one"],[2,"two"],[3,"three"]] const map2 = JSON.parse(jsonText, (key, value) => - key === "" ? new Map(value) : value, + Array.isArray(value) ? new Map(value) : value, ); console.log(map2);