序列化和反序列化`undefined`

问题描述 投票:0回答:1

undefined
不是有效的 JSON 值,因此我使用自定义替换函数来序列化它。效果很好。但是,当反序列化它时,它适用于值和数组(因此我的 reviver 函数似乎有效),但不适用于未定义键消失的对象。我做错了什么?

function serialize(data) {
   return JSON.stringify(data, function (key, value) {
      if (this[key] === undefined) {
         return '__undef__'
      }

      return value
   })
}

function deserialize(data) {
   return JSON.parse(data, function (key, value) {
      if (this[key] === '__undef__') {
         return undefined
      }

      return value
   })
}

const undef = undefined
const obj1 = { undef: undefined }

console.log(serialize(undefined));
console.log(deserialize(serialize(undefined)));

console.log(serialize([undefined]));
console.log(deserialize(serialize([undefined])));

console.log(serialize({ undef: undefined }));
console.log(deserialize(serialize({ undef: undefined })));

javascript json parsing serialization undefined
1个回答
0
投票

您的问题基本上是 [ <1 empty item> ] 是由于 JavaScript 处理带有空项的数组的方式造成的。当未定义被放置在序列化然后反序列化的数组中时,结果将具有命名的“洞”,而不是像您想要的那样显式未定义值。

因为像 jabaa 提到的那样,“如果 reviver 函数返回未定义(或不返回任何值 - 例如,如果执行落在函数末尾),则该属性将从对象中删除。”,source .

要解决此问题,您必须添加一个自定义方法来处理服务和反序列化,该方法考虑到未定义的值,以便它们不会被语言视为“漏洞”

function serialize(data) {
    return JSON.stringify(data, function (key, value) {
        return value === undefined ? '__undef__' : value;
    });
}

function deserialize(data) {

    const parsedArray = JSON.parse(data, function(key, value) {
        if (this[key] === '__undef__') {
            return undefined
         }
    });

    
    if (Array.isArray(parsedArray)) {
        for (let i = 0; i < parsedArray.length; i++) {
            // if i in parsedArray returns false if there is no value (thus empty item), so we just change it to undefined
            if (!(i in parsedArray)) {
                parsedArray[i] = undefined;
            }
        }
    }

    return parsedArray;
}

const undef = undefined;
const obj1 = { undef: undefined };

console.log(serialize(undefined)); // "__undef__"
console.log(deserialize(serialize(undefined))); // undefined

console.log(serialize([undefined])); // "["__undef__"]"
console.log(deserialize(serialize([undefined]))) // undefined

console.log(serialize({ undef: undefined })); // {"undef":"__undef__"}
console.log(deserialize(serialize({ undef: undefined }))); // undefined
© www.soinside.com 2019 - 2024. All rights reserved.