PageSourceSearch

https://adam-coster.pages.dev/_app/immutable/nodes/33.B5OPlNbq.js

js adam-coster.pages.dev collected 2026-10-03 06:27:21 UTC 14,361 bytes, 102 lines download raw bytes

1import{t as e,a as n}from"../chunks/BRuBKdOt.js";import"../chunks/B4ndRVNs.js";import{e as l}from"../chunks/D3qO8zUI.js";var t=e(`<p>When trying to take an object-oriented approach in Javscript, you'll run into the following problem: The native <code>JSON.stringify()</code> method, which works wonders for plain objects, is basically useless for class instances.</p> <p>For example:</p> <pre><code class="hljs language-js"><span class="hljs-keyword">const</span> plainObject = &lbrace;
2	<span class="hljs-attr">hello</span>: <span class="hljs-string">'world'</span>,
3	<span class="hljs-attr">something</span>: <span class="hljs-string">'else'</span>,
4	<span class="hljs-attr">nested</span>: &lbrace; <span class="hljs-attr">item</span>: &lbrace; <span class="hljs-attr">number</span>: <span class="hljs-number">10</span> &rbrace; &rbrace;,
5&rbrace;;
6<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(plainObject);
7<span class="hljs-comment">// Yields the perfect JSON string:</span>
8<span class="hljs-comment">// '&lbrace;"hello":"world","something":"else","nested":&lbrace;"item":&lbrace;"number":10&rbrace;&rbrace;&rbrace;'</span>
9
10<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyFancyClass</span> &lbrace;
11	#something;
12	<span class="hljs-title function_">constructor</span>(<span class="hljs-params"></span>) &lbrace;
13		<span class="hljs-variable language_">this</span>.<span class="hljs-property">hello</span> = <span class="hljs-string">'world'</span>;
14		<span class="hljs-variable language_">this</span>.#something = <span class="hljs-string">'else'</span>;
15	&rbrace;
16	<span class="hljs-keyword">get</span> <span class="hljs-title function_">item</span>() &lbrace;
17		<span class="hljs-keyword">return</span> &lbrace; <span class="hljs-attr">number</span>: <span class="hljs-number">10</span> &rbrace;;
18	&rbrace;
19	<span class="hljs-keyword">get</span> <span class="hljs-title function_">nested</span>() &lbrace;
20		<span class="hljs-keyword">return</span> &lbrace; <span class="hljs-attr">item</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">item</span> &rbrace;;
21	&rbrace;
22&rbrace;
23<span class="hljs-keyword">const</span> instanceOfMyFancyClass = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyFancyClass</span>();
24<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(instanceOfMyFancyClass);
25<span class="hljs-comment">// Yields:</span>
26<span class="hljs-comment">// '&lbrace;"hello":"world"&rbrace;'</span>
27</code></pre> <p>(That <code>#something</code> syntax is modern JavaScript's way of identifying private properties, which is why it doesn't show up in the JSON string.)</p> <h2 id="using-tojson"><a aria-hidden="true" tabindex="-1" href="#using-tojson"><svg viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Using <code>.toJSON()</code></h2> <p>When you call JavaScript's built-in <code>JSON.stringify()</code> function on an object, it looks for a <code>toJSON()</code> function on that object and, if such a function exists, stringifies the result of that function's return value.</p> <p>This is super handy, since it allows you to add a <code>toJSON()</code> method to your class and output a plain object for stringifying.</p> <pre><code class="hljs language-js"><span class="hljs-keyword">class</span> <span class="hljs-title class_">MyStringifiableClass</span> &lbrace;
28	#something;
29	<span class="hljs-title function_">constructor</span>(<span class="hljs-params"></span>) &lbrace;
30		<span class="hljs-variable language_">this</span>.<span class="hljs-property">hello</span> = <span class="hljs-string">'world'</span>;
31		<span class="hljs-variable language_">this</span>.#something = <span class="hljs-string">'else'</span>;
32	&rbrace;
33	<span class="hljs-keyword">
33get</span> <span class="hljs-title function_">item</span>() &lbrace;
34		<span class="hljs-keyword">return</span> &lbrace; <span class="hljs-attr">number</span>: <span class="hljs-number">10</span> &rbrace;;
35	&rbrace;
36	<span class="hljs-keyword">get</span> <span class="hljs-title function_">nested</span>() &lbrace;
37		<span class="hljs-keyword">return</span> &lbrace; <span class="hljs-attr">item</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">item</span> &rbrace;;
38	&rbrace;
39	<span class="hljs-title function_">toJSON</span>(<span class="hljs-params"></span>) &lbrace;
40		<span class="hljs-keyword">return</span> &lbrace;
41			<span class="hljs-attr">hello</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">hello</span>,
42			<span class="hljs-attr">something</span>: <span class="hljs-variable language_">this</span>.#something,
43			<span class="hljs-attr">nested</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">nested</span>,
44		&rbrace;;
45	&rbrace;
46&rbrace;
47
48<span class="hljs-keyword">const</span> stringifiableInstance = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyStringifiableClass</span>();
49<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(stringifiableInstance);
50<span class="hljs-comment">// '&lbrace;"hello":"world","something":"else","nested":&lbrace;"item":&lbrace;"number":10&rbrace;&rbrace;&rbrace;'</span>
51</code></pre> <h2 id="using-toobject-and-a-jsonstringify-replacer"><a aria-hidden="true" tabindex="-1" href="#using-toobject-and-a-jsonstringify-replacer"><svg viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Using <code>.toObject()</code> and a JSON.stringify replacer</h2> <p>But what if you don't have control over the guts of the thing you want to stringify, or for other reasons can't use <code>toJSON()</code>? Or what if you need to be able to stringify the same object in different ways?</p> <p>An approach I've seen in a few JavaScript libraries is to include a method <code>.toObject()</code> that returns a plain object representation of a class instance. Presumably the method name is mirroring the built-in <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString"><code>.toString()</code></a> method that all JavaScript objects have. In any event, having a <code>.toObject()</code> method on your classes is great for a lot of reasons, but one thing it does <em>not</em> help you with is JSON stringification.</p> <p>That is, unless you take advantage of the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter">"replacer" argument</a> in JavaScript's native <code>JSON.stringify</code> method. By updating the replacer to attempt to use <code>.toObject()</code>, and then using that method in all your custom classes (and extending built-in classes to add it), you can still use <code>JSON.stringify</code> in a meaningful way on class instances.</p> <pre><code class="hljs language-js"><span class="hljs-keyword">class</span> <span class="hljs-title class_">MyStringifiableClass</span> &lbrace;
52	#something;
53	<span class="hljs-title function_">constructor</span>(<span class="hljs-params"></span>) &lbrace;
54		<span class="hljs-variable language_">this</span>.<span class="hljs-property">hello</span> = <span class="hljs-string">'world'</span>;
55		<span class="hljs-variable language_">this</span>.#something = <span class="hljs-string">'else'</span>;
56	&rbrace;
57	<span class="hljs-keyword">get</span> <span class="hljs-title function_">item</span>() &lbrace;
58		<span class="hljs-keyword">return</span> &lbrace; <span class="hljs-attr">number</span>: <span class="hljs-number">10</span> &rbrace;;
59	&rbrace;
60	<span class="hljs-keyword">
60get</span> <span class="hljs-title function_">nested</span>() &lbrace;
61		<span class="hljs-keyword">return</span> &lbrace; <span class="hljs-attr">item</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">item</span> &rbrace;;
62	&rbrace;
63	<span class="hljs-title function_">toObject</span>(<span class="hljs-params"></span>) &lbrace;
64		<span class="hljs-keyword">return</span> &lbrace;
65			<span class="hljs-attr">hello</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">hello</span>,
66			<span class="hljs-attr">something</span>: <span class="hljs-variable language_">this</span>.#something,
67			<span class="hljs-attr">nested</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">nested</span>,
68		&rbrace;;
69	&rbrace;
70&rbrace;
71
72<span class="hljs-comment">/**
73 * <span class="hljs-doctag">@param</span> &lbrace;<span class="hljs-type">string</span>&rbrace; <span class="hljs-variable">key</span>
74 * <span class="hljs-doctag">@param</span> &lbrace;<span class="hljs-type">any</span>&rbrace; <span class="hljs-variable">value</span>
75 */</span>
76<span class="hljs-keyword">function</span> <span class="hljs-title function_">jsonStringifyToObjectReplacer</span>(<span class="hljs-params">key, value</span>) &lbrace;
77	<span class="hljs-keyword">if</span> (value &#x26;&#x26; value.<span class="hljs-property">toObject</span>) &lbrace;
78		<span class="hljs-keyword">return</span> value.<span class="hljs-title function_">toObject</span>();
79	&rbrace;
80	<span class="hljs-keyword">return</span> value;
81&rbrace;
82
83<span class="hljs-keyword">const</span> stringifiableInstance = <span class="hljs-keyword">new</span> <span class="hljs-title class_">MyStringifiableClass</span>();
84<span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(stringifiableInstance, jsonStringifyToObjectReplacer);
85<span class="hljs-comment">// And now we're back to where we started:</span>
86<span class="hljs-comment">// '&lbrace;"hello":"world","something":"else","nested":&lbrace;"item":&lbrace;"number":10&rbrace;&rbrace;&rbrace;'</span>
87</code></pre> <p>For convenience, wrap your own function around the native stringifier and use that throughout your application:</p> <pre><code class="hljs language-js"><span class="hljs-keyword">function</span> <span class="hljs-title function_">stringify</span>(<span class="hljs-params">something</span>) &lbrace;
88	<span class="hljs-keyword">return</span> <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(something, jsonStringifyToObjectReplacer);
89&rbrace;
90</code></pre> <p>You could even combine the use of <code>toJSON()</code> and <code>toObject</code> (or other custom functions, along with the built-in JSON stringifier and custom ones with your own replacers, to output different stringified versions of your class instances depending on context!</p> <h2 id="change-the-expressjs-jsonstringify-replacer"><a aria-hidden="true" tabindex="-1" href="#change-the-expressjs-jsonstringify-replacer"><svg viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Change the Express.js <code>JSON.stringify</code> replacer</h2> <p>The <a href="https://expressjs.com/">Express.js</a> framework is stellar for rapidly setting up a RESTful server. One of its many great traits is how it handles sending data back to clients: if you attempt to send some sort of JavaScript object Express will automatically JSON stringify that object for you and set the <code>Content-Type</code> header to "application/json".</p> <pre><code class="hljs language-js"><span class="hljs-comment">// Express server setup</span>
91<span class="hljs-comment">// See &lbrace;@link https://expressjs.com/en/starter/hello-world.html&rbrace;</span>
92<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
93<span class="hljs-keyword">const</span> app = <span class="hljs-title function_">express</span>();
94app.<span class="hljs-title function_">listen</span>(<span class="hljs-number">8080</span>);
95
96app.<span class="hljs-title function_">
96get</span>(<span class="hljs-string">'/'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =></span> &lbrace;
97	res.<span class="hljs-title function_">send</span>(&lbrace; <span class="hljs-attr">hello</span>: <span class="hljs-string">'world'</span> &rbrace;);
98	<span class="hljs-comment">// Client recieves '&lbrace;"hello":"world"&rbrace;' body</span>
99	<span class="hljs-comment">// with content-type header set to "application/json"</span>
100&rbrace;);
101</code></pre> <p>But what if you want to send a class instance to the client? Express uses the regular <code>JSON.stringify</code> method on the data you send, so we're right back to the original problem. Fortunately, Express lets you set any replacer you want:</p> <pre><code class="hljs language-js">app.<span class="hljs-title function_">set</span>(<span class="hljs-string">'json replacer'</span>, jsonStringifyToObjectReplacer);
102</code></pre> <p>And with that, you can simply <code>res.send(myClassInstance)</code> throughout your entire Express application, for any classes that include the <code>.toObject()</code> method.</p>`,1);function o(s){var a=t();l(42),n(s,a)}export{o as component};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.