为什么在JSON.stringify()遇到设置对象时会被忽略?

时间:2018-07-14 10:59:37

标签: javascript json set

我有一个如下的Student Java Script对象:

function Student(name, grade){
    this.name = name;
    this.grade = grade;
}

我知道我可以使用 JSON.stringify() JSON.parse()方法在本地存储中存储对象或从中获取对象。工作正常。但是我的问题在下面。

我想引入一个 Set()类型的新属性' subjects ',该属性采用唯一值并将此Student对象存储在本地存储中。我的 saveStudent()方法如下:

function saveStudent () {
    student = new Student("Rajib","1st");

    var subjects = new Set();
    subjects.add("Mathematics");
    subjects.add("Science");
    subjects.add("English");
    console.log(subjects);
    student.subjects = subjects;

    window.localStorage.setItem("student", JSON.stringify(student));
}

我可以将该对象存储在本地存储中而不会出现任何错误,并且我的控制台可以正确显示3个主题。但是,当我尝试从本地存储中检索此Student对象时,我得到的Student对象具有除' subjects '外为空的所有值。我可以知道为什么吗?

我的 getStudent()方法如下:

function getStudent () {
    var student = JSON.parse(window.localStorage.getItem("student"));
    console.log(student);
}

我的控制台显示

Object { name: "Rajib", grade: "1st", subjects: {} }

无论如何,是否有将这样的嵌套对象(其中对象的属性包含另一个对象)存储在本地存储中并检索其所有属性和值的方法?

注意:我可以通过序列化为“主题字符串”然后再次进行反序列化来解决上述问题。但是我想避免这种情况,而是想以纯Java脚本或OOP的方式来实现。

2 个答案:

答案 0 :(得分:4)

由于JavaScript中的Sets不会将其条目存储为可枚举的属性,因此这些条目对JSON.stringify函数而言并不透明。

但是,通过replacerJSON.stringify参数和reviverJSON.parse参数,提供了一种方法来影响序列化/反序列化过程已处理。

因此:


function Student(name, grade, subjects) {
  this.name = name;
  this.grade = grade;
  this.subjects = subjects || new Subjects();
}

function saveStudent(student) {
  var studentObjectAsSerialisedData = JSON.stringify(student, function(propertyKey, propertyValue) {

    // Store a set in the form a list that can be used to recreate it
    if ("subjects" === propertyKey) {
      return Array.from(propertyValue);
    }

    return propertyValue;
  });

  window.localStorage.setItem("student", studentObjectAsSerialisedData);
  console.log("saved:", studentObjectAsSerialisedData);
}

function getStudent() {
  var studentObjectAsSerialisedData = window.localStorage.getItem("student");
  var student = JSON.parse(studentObjectAsSerialisedData, function(propertyKey, propertyValue) {
    // Restore subjects from list to the set form
    if ("subjects" === propertyKey) {
      return new Set(propertyValue);
    }

    // Everything else is returned as is
    return propertyValue;
  });

  student.subjects = new Set(student.subjects);

  console.log("loaded: ", student);
  console.log("loaded subjects of student: ", Array.from(student.subjects));
}

var subjects = new Set(["Mathematics", "Science", "English"]);
var student = new Student("Rajib", "1st", subjects);
saveStudent(student);

var storedStudent = getStudent();

答案 1 :(得分:1)

其原因是JSON.stringify(set)总是返回'{}'。您应该传递JSON.stringify方法替换函数,以将主题集转换为数组,如下所示:Array.from(set),然后保存该版本。然后从localstorage获取学生对象后,应将subjects数组转换回set。因此您的代码应如下所示:

function saveStudent () {
    student = new Student("Rajib","1st");

    var subjects = new Set();
    subjects.add("Mathematics");
    subjects.add("Science");
    subjects.add("English");
    console.log(subjects);
    student.subjects = subjects;

    var stringifiedVersion = JSON.stringify(student, function (key, val) {
        if (val instanceof Set) {
            return Array.from(val);
        }
    })

    window.localStorage.setItem("student", stringifiedVersion);
}

function getStudent () {
    var student = JSON.parse(window.localStorage.getItem("student"));
    student.subjects = new Set(student.subjects);
    console.log(student);
}