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 = { 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>: { <span class="hljs-attr">item</span>: { <span class="hljs-attr">number</span>: <span class="hljs-number">10</span> } }, 5}; 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">// '{"hello":"world","something":"else","nested":{"item":{"number":10}}}'</span> 9 10<span class="hljs-keyword">class</span> <span class="hljs-title class_">MyFancyClass</span> { 11 #something; 12 <span class="hljs-title function_">constructor</span>(<span class="hljs-params"></span>) { 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 } 16 <span class="hljs-keyword">get</span> <span class="hljs-title function_">item</span>() { 17 <span class="hljs-keyword">return</span> { <span class="hljs-attr">number</span>: <span class="hljs-number">10</span> }; 18 } 19 <span class="hljs-keyword">get</span> <span class="hljs-title function_">nested</span>() { 20 <span class="hljs-keyword">return</span> { <span class="hljs-attr">item</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">item</span> }; 21 } 22} 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">// '{"hello":"world"}'</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> { 28 #something; 29 <span class="hljs-title function_">constructor</span>(<span class="hljs-params"></span>) { 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 } 33 <span class="hljs-keyword">
33get</span> <span class="hljs-title function_">item</span>() { 34 <span class="hljs-keyword">return</span> { <span class="hljs-attr">number</span>: <span class="hljs-number">10</span> }; 35 } 36 <span class="hljs-keyword">get</span> <span class="hljs-title function_">nested</span>() { 37 <span class="hljs-keyword">return</span> { <span class="hljs-attr">item</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">item</span> }; 38 } 39 <span class="hljs-title function_">toJSON</span>(<span class="hljs-params"></span>) { 40 <span class="hljs-keyword">return</span> { 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 }; 45 } 46} 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">// '{"hello":"world","something":"else","nested":{"item":{"number":10}}}'</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> { 52 #something; 53 <span class="hljs-title function_">constructor</span>(<span class="hljs-params"></span>) { 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 } 57 <span class="hljs-keyword">get</span> <span class="hljs-title function_">item</span>() { 58 <span class="hljs-keyword">return</span> { <span class="hljs-attr">number</span>: <span class="hljs-number">10</span> }; 59 } 60 <span class="hljs-keyword">
60get</span> <span class="hljs-title function_">nested</span>() { 61 <span class="hljs-keyword">return</span> { <span class="hljs-attr">item</span>: <span class="hljs-variable language_">this</span>.<span class="hljs-property">item</span> }; 62 } 63 <span class="hljs-title function_">toObject</span>(<span class="hljs-params"></span>) { 64 <span class="hljs-keyword">return</span> { 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 }; 69 } 70} 71 72<span class="hljs-comment">/** 73 * <span class="hljs-doctag">@param</span> {<span class="hljs-type">string</span>} <span class="hljs-variable">key</span> 74 * <span class="hljs-doctag">@param</span> {<span class="hljs-type">any</span>} <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>) { 77 <span class="hljs-keyword">if</span> (value && value.<span class="hljs-property">toObject</span>) { 78 <span class="hljs-keyword">return</span> value.<span class="hljs-title function_">toObject</span>(); 79 } 80 <span class="hljs-keyword">return</span> value; 81} 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">// '{"hello":"world","something":"else","nested":{"item":{"number":10}}}'</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>) { 88 <span class="hljs-keyword">return</span> <span class="hljs-title class_">JSON</span>.<span class="hljs-title function_">stringify</span>(something, jsonStringifyToObjectReplacer); 89} 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 {@link https://expressjs.com/en/starter/hello-world.html}</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> { 97 res.<span class="hljs-title function_">send</span>({ <span class="hljs-attr">hello</span>: <span class="hljs-string">'world'</span> }); 98 <span class="hljs-comment">// Client recieves '{"hello":"world"}' body</span> 99 <span class="hljs-comment">// with content-type header set to "application/json"</span> 100}); 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.