#javascript #json #reviver-function
#javascript #json #reviver-функция
Вопрос:
Ссылка на JSBin, чтобы вы могли быстро запустить код.
Проблема в комментариях, но из того, что говорится в документации о том, как работает reviver (это ужасное название), если вы не возвращаете значение или если вы возвращаете undefined
, то это свойство должно быть удалено из объекта. Если вы возвращаете нетрансформированное значение, оно остается прежним.
Тем не менее, когда я это тестирую, похоже, что удаляется весь объект. Первый пример работает просто отлично, четные числа преобразуются в отрицательные, а нечетные числа остаются неизменными.
Но во втором примере я даже не получаю объект обратно, просто неопределенный. Итак, я неправильно читаю документацию или что-то еще не так?
Результат просто не определен во втором примере.
var obj = {
one: 1,
innerObj: {
two: 2,
four: 4
},
two: 2,
three: 3,
four: 4
},
b = {},
json = JSON.stringify(obj);
/**
* This works as expected.
*/
b = JSON.parse(json, function (name, value) {
if (value % 2 === 0) {
return -value;
}
return value;
});
console.log(b);
/**
[object Object] {
four: -4,
innerObj: [object Object] {
four: -4,
two: -2
},
one: 1,
three: 3,
two: -2
}
*/
obj = {
one: 1,
innerObj: {
two: 2,
four: 4
},
two: 2,
three: 3,
four: 4
};
b = {};
json = JSON.stringify(obj);
/**
* This does not work as expected, instead of deleting the property on the object, the entire object returns undefined.
*/
b = JSON.parse(json, function (name, value) {
if (value % 2 === 0) {
return -value;
}
});
console.log(b);
// undefined
Ответ №1:
Ваш второй пример не приведен return value;
.
Но даже если вы это сделали, это должно было удалить только свойства, которые возвращались undefined
как значение, и я думаю, вы нашли ошибку (может быть?).
В одном из MDN
JSON.parse
примеров говорится, что последний ключ — это ""
когда JSON.parse
вызывается
Мне удалось воспроизвести ваш код с undefined
ошибкой, и кажется, что если вы вернете значение для ""
ключа, например
if (name == "") {
return value;
}
похоже, что это работает так, как ожидалось.
obj = {
one: 1,
innerObj: {
two: 2,
four: 4
},
two: 2,
three: 3,
four: 4
};
b = {};
json = JSON.stringify(obj);
/**
* This does not work as expected, instead of deleting the property on the object, the entire object returns undefined.
*/
b = JSON.parse(json, function (name, value) {
if (value % 2 === 0) {
return -value;
}
if (name == "") {
return value;
}
});
console.log(b);
// { two: -2, four: -4 }
Редактировать:
Итак, читая спецификацию ECAMScript JSON.parse(text [, reviver]), кажется, что это ожидаемое поведение. Когда описывается поведение при вызове reviver
функции, последним шагом после вызова всех DefineOwnProperty
элементов является
Возвращает результат вызова абстрактной операции Walk, передавая root и пустую строку.
Итак, когда вы не возвращаете значение для ''
имени в вашей функции reviver, она понимает, что она должна удалить это, что означает, что весь объект должен быть возвращен, в результате чего он будет undefined
для JSON.parse
возврата.
Это объясняет озабоченность в документах MDN, когда говорится
обязательно возвращайте все нетрансформированные значения как есть
Но я согласен, что следует более подробно рассказать о том, как работают эти небольшие нюансы.
Комментарии:
1. Я обновил свой код для проверки. Теперь это работает для внешнего объекта, он возвращает двойку и четыре из этого. Но innerObj по-прежнему полностью удаляется. Итак, это частичное решение, но я бы ожидал сохранить оба набора данных в этом случае. Это некорректное поведение, но я понятия не имею, почему.
2. но
innerObj
должен быть удален, так как любойobject
при применении%
оператор возвращаетundefined
. вы должны ввести check перед его применением, используяtypeof
и возвращаемыйvalue
, когда это неnumber
, например3. @MichaelRyanSoileau Я провел некоторое исследование спецификации JSON.parse ECAMScript и обновил свой ответ. Кажется, что это желаемое поведение, когда
undefined
возвращается, когда''
является ключом дляreviver
функции.