liveBook · Manning

Serialization

As explained in The Joy of JavaScript

The process of converting data or objects from one representation into another for storage, transmission, or reconstruction.

Serialization converts an object from one representation to another, commonly from in-memory data to a file or transferable format. Deserialization, also called hydration, reconstructs in-memory objects from that representation. section 7.4.3 section 9.2.3

A robust serializer lets each object control its external representation. A global symbol such as Symbol.for('toJson') provides a discoverable hook without colliding with ordinary method names; a generic helper uses the hook when available and otherwise falls back to JSON.stringify. section 7.4.3

Serializing a ledger

A Block can emit a tailored JSON summary containing its index, hashes, timestamp, data count, data, and version. A ledger is converted to an array, serialized block by block, joined with a delimiter, and converted into a UTF-8 Buffer suitable for writing to a file or sending over a network.

Serialization also works incrementally with streams. An async generator reads delimited JSON blocks from a file, parses each block as it becomes available, and yields it without loading the entire file. Consumers can hydrate each object and validate it immediately. section 9.2.3

Listing 9.8 Async generator that sends blocks read from a file
async function* generateBlocksFromFile(file) {                         #1
   try {
      await fsp.access(file, fs.constants.F_OK | fs.constants.R_OK);
 
      const dataStream = fs.createReadStream(file,
           { encoding: 'utf8', highWaterMark: 64 });
 
      let previousDecodedData = '';
 
      for await (const chunk of dataStream) {
         previousDecodedData += chunk;
         let separatorIndex;
         while ((separatorIndex = previousDecodedData.indexOf(';')) >= 0) {
         
            const decodedData = previousDecodedData.slice(0, 
               separatorIndex + 1);
  
            const blocks = tokenize(';', decodedData)
                .filter(str => str.length > 0)
                .map(str => str.replace(';', ''));
                
             for (const block of blocks) {
                yield JSON.parse(block);                               #2
             }
             previousDecodedData = previousDecodedData.slice(
                 separatorIndex + 1);
         }
      }
      if (previousDecodedData.length > 0) {        
         yield JSON.parse(previousDecodedData);                        #2
      }
   }
   catch (e) {
      console.error(`Error processing file: ${e.message}`);
      throw e;
   }
}

Shows an async generator that reads file chunks, separates serialized blocks, parses JSON, and yields each decoded object. section 9.2.3

Listing 9.10 Validating a stream of blocks generated from a file
   let validBlocks = 0;
   const chain = new Blockchain();             #1
   let skippedGenesis = false
   for await (const blockData of generateBlocksFromFile('blocks.txt')) {
      if (!skippedGenesis) { 
         skippedGenesis = true;
         continue;                             #2
      }
      const block = 
        new Block(blockData.index, chain.top.hash, blockData.data,      
            blockData.difficulty);
 
      chain.push(block);                       #3
 
      if (block.validate().isFailure) {        #4
         continue;
      }
      validBlocks++
   }
 
   console.log(validBlocks) // 2

Shows the consumer side: skip the genesis block, hydrate each decoded object into a Block, add it to a chain, and validate it. section 9.2.3

How The Joy of JavaScript covers it

How deep it goes
Explains custom symbol hooks, JSON fallback, composed buffer pipelines, streamed parsing, hydration, and validation.
Examples
Uses blockchain blocks, delimiter-separated ledger files, UTF-8 buffers, async file generators, and validation of reconstructed chains.
What it assumes
Assumes familiarity with JavaScript objects, JSON, files, buffers, generators, and asynchronous iteration.
What you can do after
Build it from scratch by defining object-specific JSON hooks and composing serializers for complete or streamed file representations.
How it connects
Connects serialization with JSON, symbols, deserialization, hydration, streams, async generators, async iteration, currying, and composition.

Also explained in

Compare how 24 books explain serialization →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Joy of JavaScript. The section links point to the parts of the book it draws on.