Serializing & Deserializing (JSON)

devfish·2023년 2월 15일
0

Javascript

목록 보기
27/30
post-thumbnail

What is JSON?

Summary of Intro to JSON & Beginner's Guide to JSON:

JSON (JavaScript Object Notation): a lightweight data-interchange format and an ideal language for data-interchange since it is..

  • easy for humans to read & write
  • easy for machines to parse and generate
  • a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, etc.
  • transmission size is small
  • like javascript objects, so simple to process in web front-end

It is one of the most popular data-interchange standards for a good reason. It is not, however, the be-all and end-all solution for all situations (e.g. other standards such as YAML are more appropriate for stuff like config files.)

JSON is built on two structures:

  • A collection of name/value pairs - realized as an object, record, struct, dictionary, hash table, keyed list, or associative array in various languages
  • An ordered list of values - realized as an array, vector, list, or sequence in most languages

These are universal data structures supported by virtually all modern programming languages in one form or another. It makes sense that a data format that is interchangeable with programming languages also be based on these structures.

In JSON, they take on the form of an object, which is an unordered set of name/value pairs that beings with {left brace and ends with }right brace. Each name is followed by :colon and the name/value pairs are separated by ,comma.

The Rise of JSON

const message = {
  sender: "김코딩",
  receiver: "박해커",
  message: "해커야 오늘 저녁 같이 먹을래?",
  createdAt: "2021-01-12 10:10:10"
}

If you want to send an object (like above) to another program via the network, the sender and receiver of the message needs to be using the same program, or the message needs to be a universal format (e.g. string) that can be generally read anywhere (what is referred to as transferable condition).

An object's contents cannot be stringified with type conversion/coercion (for instance, methods such as message.toString() or type conversion such as String(message) will only return [object Object].

(Sidebar: check this out for a deeper explanation of [object Object]. TLDR: Every object has a toString() method that is automatically called when the object is to be represented as a text value or when an object is referred to in a manner in which a string is expected. Object.prototype.toString is a method that detects the class of an object and tells you what it is (as in, it prints out the name of the class you passed into toString.)

Serialize & De-Serialize

Utilizing JSON provides a simple solution to this problem: you can transform the object into a JSON object to send it over a network, and likewise transform a JSON object to an object when you fetch or receive something over a network. It is

  • JSON.stringify: converts object to JSON (serializing)
  • JSON.parse: converts JSON into object (de-serializing)

JS Objects vs JSON Objects

JS ObjectJSON
KeyDoes not need double quotes
{ key : "property" }
Must be wrapped in double quotes
'{"key":"property"}'
String valueCan be wrapped in single quotes
{ "key" : 'property' }
Must be wrapped in double quotes
'{"key":"property"}'
Space Between Key & ValueIs allowed
{"key" : 'property'}
Not allowed '{"key":"property"}'
Space Between Key-Value PairsIs allowed
{ "key":'property', num:1 }
Not allowed
'{"key":"property","num":1}'

Implementing JSON.Stringify via Recursion

  • Single/double quotes of strings, and brackets of arrays are removed when used as embedded expressions in template literals, so the quotes and brackets need to be separately added to the template literal!
  • Checking for Null: obj === null (typeof null is equal to 'object')
  • Transforming objects (key-value pairs) into a JSON format involves extracting the keys and values and concantenating them all into a string via a loop
  • Map method does not actually change the existing array, but rather creates a new array of mutated data. So you need a variable to hold what it spits out to use what the map method produces!

//REFERENCE CODE
function stringifyJSON(obj) {
  if (obj === null) {
    return "null";
  }
  if (typeof obj === "number" || typeof obj === "boolean") {
    return String(obj);
  }
  if (typeof obj === "string") {
    return `"${obj}"`;
  }
  //if an object is an array
  if (Array.isArray(obj)) {
    const result = [];
    obj.forEach(function (element) {
      result.push(stringifyJSON(element))
    })
    return `[${result}]`;
  }
  //if it's an object (array also is an 'object' but was already filtered above
  if (typeof obj === "object") {
    let result = "";
    for (let key in obj) {
      if (obj[key] === undefined || typeof obj[key] === "function") {
        result = String(result);
      } else {
        result = result + `${stringifyJSON(key)}:${stringifyJSON(obj[key])},`;
      }
    }
    result = result.substr(0, result.length - 1);
    return `{${result}}`;
  }
};

if (typeof window === "undefined") {
  module.exports = stringifyJSON;

//SUB-OPTIMAL CODE TO LEARN WHAT ***NOT*** TO DO 
function stringifyJSON(obj) {
  if (typeof obj === 'string'){
    return `"${obj}"`; //add double quotes for string
  }
  
  if(Array.isArray(obj)){
    //if (!obj.length) return `[]`; -> not necessary!
    let result = obj.map(el => stringifyJSON(el)); //map result needs to be contained somewhere! Does not change the original array
      return `[${result}]`;
  }
  
  if(typeof obj === 'object' && obj !== null){
    // if (!Object.keys(obj).length) return `{}`; -> not necessary!
    const keys = [];
    const values = [];
    let result = '';
	
    //four for loops! suboptimal. can be done within one for loop
    for (let key in obj){ //filter out the functions and undefined
      if(typeof obj[key] === 'function' || typeof obj[key] === 'undefined')
      return `{}`;
    }
    
    for (let key of Object.keys(obj)) {keys.push(stringifyJSON(key));} 
    for (let val of Object.values(obj)) {values.push(stringifyJSON(val));}
    for (let i = 0; i < keys.length; i++){
      result += keys[i] + ":" + values[i] + ',';
    }

    result = result.slice(0, -1); //cut off the last comma
    return `{${result}}`;
  }else{
    //number, boolean, null
    return `${obj}`;
  }
};

References

Introducing JSON
A beginner’s guide to JSON, the data format for the internet
What Is [object Object] in JavaScript: Object.prototype.toString

<For further Study>

  • 재귀 함수와 메모리 사용량 간의 관계 (javascript recursion memory leak)
  • 꼬리 재귀 (tail recursion in js)
  • 하노이의 탑 재귀 (js tower of hanoi in recursion)
  • 조합 재귀 함수 (js combination in recursion)
profile
la, di, lah

0개의 댓글