This document describes operations performed to produce, or parse, the flatted output.\hypertarget{md_sfcode_node_modules_flatted_SPECS_autotoc_md10807}{}\doxysection{stringify(any) =$>$ flatted\+String}\label{md_sfcode_node_modules_flatted_SPECS_autotoc_md10807}
The output is always an {\ttfamily Array} that contains at index {\ttfamily 0} the given value.

If the value is an {\ttfamily Array} or an {\ttfamily Object}, per each property value passed through the callback, return the value as is if it\textquotesingle{}s not an {\ttfamily Array}, an {\ttfamily Object}, or a {\ttfamily string}.

In case it\textquotesingle{}s an {\ttfamily Array}, an {\ttfamily Object}, or a {\ttfamily string}, return the index as {\ttfamily string}, associated through a {\ttfamily Map}.

Giving the following example\+:


\begin{DoxyCode}{0}
\DoxyCodeLine{flatted.stringify('a');                     // ["{}a"{}]}
\DoxyCodeLine{flatted.stringify(['a']);                   // [["{}1"{}],"{}a"{}]}
\DoxyCodeLine{flatted.stringify(['a', 1, 'b']);           // [["{}1"{},1,"{}2"{}],"{}a"{},"{}b"{}] }

\end{DoxyCode}


There is an {\ttfamily input} containing {\ttfamily \mbox{[}array, \char`\"{}a\char`\"{}, \char`\"{}b\char`\"{}\mbox{]}}, where the {\ttfamily array} has indexes {\ttfamily \char`\"{}1\char`\"{}} and {\ttfamily \char`\"{}2\char`\"{}} as strings, indexes that point respectively at {\ttfamily \char`\"{}a\char`\"{}} and {\ttfamily \char`\"{}b\char`\"{}} within the input {\ttfamily \mbox{[}array, \char`\"{}a\char`\"{}, \char`\"{}b\char`\"{}\mbox{]}}.

The exact same happens for objects.


\begin{DoxyCode}{0}
\DoxyCodeLine{flatted.stringify('a');                     // ["{}a"{}]}
\DoxyCodeLine{flatted.stringify(\{a: 'a'\});                // [\{"{}a"{}:"{}1"{}\},"{}a"{}]}
\DoxyCodeLine{flatted.stringify(\{a: 'a', n: 1, b: 'b'\});  // [\{"{}a"{}:"{}1"{},"{}n"{}:1,"{}b"{}:"{}2"{}\},"{}a"{},"{}b"{}] }

\end{DoxyCode}


Every object, string, or array, encountered during serialization will be stored once as stringified index.


\begin{DoxyCode}{0}
\DoxyCodeLine{// per each property/value of the object/array}
\DoxyCodeLine{if (any == null || !/object|string/.test(typeof any))}
\DoxyCodeLine{  return any;}
\DoxyCodeLine{if (!map.has(any)) \{}
\DoxyCodeLine{  const index = String(arr.length);}
\DoxyCodeLine{  arr.push(any);}
\DoxyCodeLine{  map.set(any, index);}
\DoxyCodeLine{\}}
\DoxyCodeLine{return map.get(any); }

\end{DoxyCode}


This, performed before going through all properties, grants unique indexes per reference.

The stringified indexes ensure there won\textquotesingle{}t be conflicts with regularly stored numbers.\hypertarget{md_sfcode_node_modules_flatted_SPECS_autotoc_md10808}{}\doxysection{parse(flatted\+String) =$>$ any}\label{md_sfcode_node_modules_flatted_SPECS_autotoc_md10808}
Everything that is a {\ttfamily string} is wrapped as {\ttfamily new String}, but strings in the array, from index {\ttfamily 1} on, is kept as regular {\ttfamily string}.


\begin{DoxyCode}{0}
\DoxyCodeLine{const input = JSON.parse('[\{"{}a"{}:"{}1"{}\},"{}b"{}]', Strings).map(strings);}
\DoxyCodeLine{// convert strings primitives into String instances}
\DoxyCodeLine{function Strings(key, value) \{}
\DoxyCodeLine{  return typeof value === 'string' ? new String(value) : value;}
\DoxyCodeLine{\}}
\DoxyCodeLine{// converts String instances into strings primitives}
\DoxyCodeLine{function strings(value) \{}
\DoxyCodeLine{  return value instanceof String ? String(value) : value;}
\DoxyCodeLine{\} }

\end{DoxyCode}


The {\ttfamily input} array will have a regular {\ttfamily string} at index {\ttfamily 1}, but its object at index {\ttfamily 0} will have an {\ttfamily instanceof String} as {\ttfamily .a} property.

That is the key to place back values from the rest of the array, so that per each property of the object at index {\ttfamily 0}, if the value is an {\ttfamily instanceof} String, something not serializable via JSON, it means it can be used to retrieve the position of its value from the {\ttfamily input} array.

If such {\ttfamily value} is an object and it hasn\textquotesingle{}t been parsed yet, add it as parsed and go through all its properties/values.


\begin{DoxyCode}{0}
\DoxyCodeLine{// outside any loop ...}
\DoxyCodeLine{const parsed = new Set;}
\DoxyCodeLine{}
\DoxyCodeLine{// ... per each property/value ...}
\DoxyCodeLine{if (value instanceof Primitive) \{}
\DoxyCodeLine{  const tmp = input[parseInt(value)];}
\DoxyCodeLine{  if (typeof tmp === 'object' \&\& !parsed.has(tmp)) \{}
\DoxyCodeLine{    parsed.add(tmp);}
\DoxyCodeLine{    output[key] = tmp;}
\DoxyCodeLine{    if (typeof tmp === 'object' \&\& tmp != null) \{}
\DoxyCodeLine{      // perform this same logic per}
\DoxyCodeLine{      // each nested property/value ...}
\DoxyCodeLine{    \}}
\DoxyCodeLine{  \} else \{}
\DoxyCodeLine{    output[key] = tmp;}
\DoxyCodeLine{  \}}
\DoxyCodeLine{\} else}
\DoxyCodeLine{  output[key] = tmp; }

\end{DoxyCode}


As summary, the whole logic is based on polluting the de-\/serialization with a kind of variable that is unexpected, hence secure to use as directive to retrieve an index with a value.

The usage of a {\ttfamily Map} and a {\ttfamily Set} to flag known references/strings as visited/stored makes {\bfseries{flatted}} a rock solid, fast, and compact, solution. 