Serialize and Deserialize JavaScript Class Objects In Front End Applications

The drawback of using JavaScript classes in your frontend application is that we cannot pass it to or receive it from the backend as class object. We need to serialize and deserialize it.

(In this post, I’m using the chess board and pieces example I shared previously to explain JavaScript inheritance and polymorphism in React application.)

Serialization means to convert your data structure into a suitable form for transmission. In our case, we need to pass our data as pure JSON object, that is, all the methods should be removed from the class object.

Conversely, deserialization means to convert the received data into the data structure we want to use in our application. Here, we are transmitted a 2D-array of JSON objects, and we want to convert it back to our class objects.

For a single object, we’d do something like below:


const rook = new Rook({ color: "black", icon: "rook", player: 2 });

const serializeObject = (obj) => {
  return JSON.parse(JSON.stringify(rook));
}

const deserializeObject = (obj) => {
  return new Rook(obj);
}

console.log("original object:", rook);

const serializedObj = serializeObject(rook);

console.log("serialized object:", serializedObj);

const deserializeObj = deserializeObject(serializedObj);
console.log("deserialize object:", deserializeObj);

The expected result:

 original object: Rook { color: 'black', icon: 'rook', player: 2 }
 serialized object: { color: 'black', icon: 'rook', player: 2 }
 deserialize object: Rook { color: 'black', icon: 'rook', player: 2 }

Note the original object before serialization is exactly the same as after deserialization. Also note that in this single example we’re using Rook class to create a new object at the time of deserialization.

But dynamically, we won’t know the class of the JSON object because the class information was stripped off it on serialization. As a workaround, we add the information about the class that piece belongs to in the piece as pieceType property, and set it at the time of any piece creation.

class Piece {
  constructor({ color, icon, player, pieceType }) {
    this.color = color;
    this.icon = icon;
    this.player = player;
    this.pieceType = pieceType;
  }

// ...

const board = [
  [
    new Rook({ pieceType: "rook", color: "black", icon: "rook", player: 2 }),
    new Knight({ pieceType: "knight", color: "black", icon: "knight", player: 2 }),
    //...
  ],
//...
];
}

For Serialization and deserialization of the board, which is a 2D-array of pieces, we need to map piece information in the JSON object to its class, so that we can recreate it dynamically. That we do by creating and using a quick lookup piecesMap hash:

const piecesMap = {
  rook: Rook,
  bishop: Bishop,
  pawn: Pawn,
  knight: Knight,
  queen: Queen,
  king: King
}

Now we can serialize and deserialize our board dynamically:

const serializeBoard = (board) => JSON.parse(JSON.stringify(board));

const serializedBoardObj = serializeBoard(board);

const deserializeBoard = (board) => board.map(row => row.map(col => col ? new piecesMap[col.pieceType](col) : null));

const deserializedBoardObj = deserializeBoard(serializedBoardObj);

See also