Sunday, September 25, 2022

Converting a JavaScript Object to a String

Angular and JavaScript

Sometimes it becomes necessary to convert an object into a string in order to view or store it. For the purpose of debugging, a simple console.log() will suffice, as just about any modern browser’s Dev Tools will provide a pretty printed version of an object. Meanwhile, relying on implicit conversion when writing an object to any other location will only result in the utterly useless “[object Object]” string. Far better results can be achieved using JavaScript’s built-in JSON.stringify() method or by writing your own conversion function. Each of these will produce differing results, so it pays to carefully consider each option before deciding which approach best suits your requirements. With that in mind, we are going to try our hand at a few strategies here, including using the toSting() method, custom conversion methods, as well as the aforementioned JSON.stringify() in today’s web development tutorial.

Looking to supplement your JavaScript with some solid HTML? Check out our list of the Best Online Courses to Learn HTML.

The toString() Method in JavaScript

For the purposes of demonstration, here is a class that contains some attributes as well as a method. Setting a paragraph elements innerText to the person instance invokes its inherited toString() method, which prints the ubiquitous “[object Object]”. Here is how that looks in JavaScript code:

'use strict';

const appendParagraph = (content) => {
  const para = document.createElement("p");
  para.innerText = content;
  document.body.appendChild(para);
};

class Person {
  constructor(name, location) {
    this.name = name;
    this.location = location;
  }
  sayHello = () => appendParagraph("Hi! I'm " + this.name);
  toString = () => "Hi! I'm " + this.name 
                 + " and I live at " + this.location;
}
const person = new Person(
  'Rob', 
  {
    city: 'Ottawa',
    country: 'Canada',
    phoneNumbers: ['555-1234', '555-2345'],
  }
);
appendParagraph(person); // [object Object]
person.sayHello();       // Hi! I'm Rob

As stated in the introduction, it is not at all helpful. But that is exactly the point, as each class is responsible for implementing its own meaningful instance method. So let’s add toString() to our class so that we get a more informative description:

class Person {
  constructor(name, location) {
    this.name = name;
    this.location = location;
  }
  sayHello = () => appendParagraph("Hi! I'm " + this.name);
  toString = () => "Hi! I'm " + this.name 
                 + " and I live at " + this.location;
}
const person = new Person(
  'Rob', 
  {
    city: 'Ottawa',
    country: 'Canada',
    phoneNumbers: ['555-1234', '555-2345'],
  }
); 
//Prints "Hi! I'm Rob and I live at [object Object]"
appendParagraph(person); 

It is an improvement, but you can see how we run into the same issue with child objects.

Read: Project Management Tools for Web Developers

Using a Custom Conversion Method in JavaScript

For optimal flexibility, you may want to consider writing a generic conversion method that you can then invoke from an instance’s toString(). This one uses recursion to handle nested objects. There is even some logic to distinguish between objects and arrays, so that they each get their own formatting (i.e. curly braces ({}) for objects versus square brackets ([]) for arrays:

const convert = obj => (
  Object.entries(obj)
    .map(([key, value]) => (
      value === Object(value)
        ? (Array.isArray(value) 
          ? `${key}[${convert(value)}]` 
          : `${key}{${convert(value)}};`)
        : `${key}:${value};`
    ))
    .join(' ')
);

class Person2 {
  constructor(name, age, location) {
    this.name = name;
    this.age = age;
    this.location = location;
  }
  sayHello = () => appendParagraph("Hi! I'm " + this.name);
  toString = () => convert(this);
}
const person2 = new Person2(
  'Charlotte',
  29,
  {
    city: 'London',
    country: 'UK',
    phoneNumbers: ['666-2112', '666-5150'],
  }
);
// name:Charlotte; age:29; location{city:London; country:UK; 
// phoneNumbers[0:666-2112; 1:666-5150;]}; sayHello{}; toString{};
appendParagraph(person2);

Using JSON.stringify() in JavaScript

This is the only native JavaScript function that turns any object to a string; all you need to do is call JSON.stringify(OBJECT) and it will turn an object or array into a JSON (JavaScript Object Notation) encoded string. It is ideal for serializing objects into strings for storing in a database because most support the JSON data type. To convert the string back into an Object, there’s the JSON.parse(STRING) method.

Here is the JSONified text for person2:

//{"name":"Charlotte","age":29,"location":{"city":"London",
//"country":"UK","phoneNumbers":["666-2112","666-5150"]}}
appendParagraph(JSON.stringify(person2));

As you can see, the output does not look all that different from that of our custom function, except that attribute names and strings are always enclosed in quotes and fields are comma delimited.

Altering JSON.stringify’s Output

JSON.stringify() is actually a lot more versatile than people give it credit for, thanks to its optional 2nd and 3rd parameters:

JSON.stringify(value, replacer, spaces)

These are a replacer function and spaces. The replacer is a function or array that can affect the stringification process by either altering the formatting or even filtering attributes. The space parameter controls spacing in the generated string by activating pretty print mode and setting the number of spaces for indentations.

Read: HTML, CSS, and JavaScript Tools and Libraries

The replacer Parameter in JavaScript

As mentioned above, the replacer parameter can be either a function or an array. As a function, it takes two parameters: the key and the value being stringified. The object in which the key was found is provided as the replacer’s this parameter (as long as web developers are not using an arrow function). Initially, the replacer function is called with an empty string as key representing the object being stringified. It is then called for each object attribute or array element being stringified.

We can use a replacer function to remove fields based on their value or type. In the following example, all numbers are removed from the output, resulting in person2’s age to be omitted:

const replacer = (key, value) => typeof value === 'number' 
                                 ? undefined 
                                 : value;
                                 
//{"name":"Charlotte","location":{"city":"London",
// "country":"UK","phoneNumbers":["666-2112","666-5150"]}}
appendParagraph(JSON.stringify(person2, replacer));

Rather than exclude certain fields, we can provide an array whose values indicate the names of the properties in the object that should be included in the resulting JSON string.

//{"name":"Charlotte","age":29}
appendParagraph(JSON.stringify(person2, ['name', 'age']));

Pretty Printing with the spaces Parameter and JavaScript

The spaces argument may be used to control spacing in the final string. Like the replacer function, it also accepts two different types:

  1. In the case of a number, successive levels in the stringification will each be indented by this many space characters, up to a maximum of 10.
  2. In the case of a string, successive levels will be indented by this string, or the first ten characters.

This JSON.stringify() invocation produces an indentation of two spaces:

appendElement(JSON.stringify(person2, null, '  '), 'pre');
/*
{
  "name": "Charlotte",
  "age": 29,
  "location": {
    "city": "London",
    "country": "UK",
    "phoneNumbers": [
      "666-2112",
      "666-5150"
    ]
  }
}
*/

Using a tab character mimics the “standard” pretty-print appearance:

appendElement(JSON.stringify(person2, null, '\t'), 'pre');
/*
{
	"name": "Charlotte",
	"age": 29,
	"location": {
		"city": "London",
		"country": "UK",
		"phoneNumbers": [
			"666-2112",
			"666-5150"
		]
	}
}
*/

Final Thoughts on Converting a JavaScript Object to a String

JavaScript offers a few ways to convert an object into a string for either display or persisting. These range from the built-in JSON.stringify() method, overriding toString(), to writing your own conversion function. Each of these approaches can be seen in the Codepen demo. JSON.stringify() is an excellent choice for persisting objects and arrays to a database, while the other two options are more appropriate for presenting an object in a human-readable form.

Read more JavaScript web development tutorials.

Rob Gravelle
Rob Gravelle
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.

Popular Articles

Featured