【问题标题】:Why are set objects ignored when encountered by JSON.stringify()? [duplicate]为什么 JSON.stringify() 遇到 set 对象时会被忽略? [复制]
【发布时间】:2018-12-22 14:00:44
【问题描述】:

我有一个 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 个主题。但是,当我尝试从本地存储中检索这个学生对象时,我得到的学生对象的所有值都是空的,但 'subjects' 除外。我可以知道为什么吗?

我的getStudent()方法如下:

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

我的控制台显示

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

有没有办法在本地存储中存储嵌套对象(其中对象的属性包含另一个对象)并检索其所有属性和值?

注意:我可以通过序列化为主题字符串然后再次反序列化来解决上述问题。但我想避免这种情况,并希望以纯 Java Script 或 OOP 的方式进行。

【问题讨论】:

  • 这个问题的观点是 duplicate 所不具备的。 OP 的@RLD 不明白问题在于subject 属性的性质——它是Set。但是,链接问题的发布者了解 Sets 不能简单地字符串化,并且正在寻找一种方法来实现这一点。我们可以多一点同理心来考虑这篇文章,从而利用这个机会进行教育以进行改进。
  • 感谢@Igwe Kalu 的体贴。你说得对,我从嵌套对象的角度想,但问题出在 Set 对象上。

标签: javascript json set


【解决方案1】:

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

但是,通过JSON.stringifyreplacer 参数和JSON.parsereviver 参数,提供了一种方法来影响在序列化/反序列化过程中遇到的项目的处理方式。

因此:


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();

【讨论】:

    【解决方案2】:

    这是因为JSON.stringify(set) 总是返回'{}'。您应该通过JSON.stringify 方法替换函数将主题集转换为数组,如下所示:Array.from(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);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-06-17
      • 2013-12-28
      • 2018-08-10
      • 1970-01-01
      • 2017-05-26
      • 1970-01-01
      • 1970-01-01
      • 2018-06-14
      • 2011-11-18
      相关资源
      最近更新 更多