Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are set objects ignored when encountered by JSON.stringify()? [duplicate]

I have a Student Java Script object as follows:

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

I know I can store and retrieve this object to/from Local Storage using JSON.stringify() and JSON.parse() method. It works fine. But my problem is below.

I want to introduce a new property 'subjects' of Set() type that takes unique values and store this Student object in Local Storage. My saveStudent() method is as follows:

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

I can store this object in Local Storage without any error and also my console displays the 3 subjects properly. But when I try to retrieve this Student object from Local Storage, I get Student object with all the values except 'subjects' which is empty. May I know why?

My getStudent() method is as follows:

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

My console shows

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

Is there anyway to store nested object(where property of object contains another object) as such in Local Storage and retrieve with all its properties and values?

Note: I can solve the above by serializing to String of Subjects and then deserializing again. But I want to avoid that and want to do it in pure Java Script or OOPs way.

like image 217
RLD Avatar asked Feb 18 '26 23:02

RLD


1 Answers

Because Sets in JavaScript don't store its entries as enumerable properties, the entries are not transparent to the JSON.stringify function.

However, by the replacer parameter of JSON.stringify and the reviver parameter of JSON.parse, provisions are given for a means to influence how an item encountered in the serialisation/deserialisation process is handled.

Hence:

  • Storing your data, use JSON.stringify's replacer to transform the Set to an array --> Array.from( Set( ... ) ).

  • Retrieving the stored data, use JSON.parse's reviver to transform the array back to a Set --> new Set( [ ... ] ).


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();
like image 149
Rick Avatar answered Feb 20 '26 11:02

Rick



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!