title: How to serialize an object in powershell to json and get identical result in PS desktop and core?
body: <p><strong>Prolog</strong></p>
  <p>It turns out that in my case it is important to understand the source of the objects - it is a JSON payload from a REST API response. Unfortunately, <strong>JSON -&gt; Object</strong> conversion produces different results on PS desktop vs PS core. On desktop the numbers are deserialized into <code>Int32</code> types, but on core - to <code>Int64</code> types. From that it follows that I cannot use <code>Export-CliXml</code>, because the binary layout of the objects is different.</p>
  <p><strong>Main question</strong></p>
  <p>I have a unit test that needs to compare the actual result with an expected. The expected result is saved in a json file, so the procedure is:</p>
  <ol>
  <li>Convert the actual result to json string</li>
  <li>Read the expected result from disk to string</li>
  <li>Compare the actual and the expected as strings</li>
  </ol>
  <p>Unfortunately, this scheme does not work because PS desktop <code>ConvertTo-Json</code> and PS core <code>ConvertTo-Json</code> do not produce identical results. So, if the expected result was saved on desktop and the test runs on core - boom, failure. And vice versa.</p>
  <p>One way is to keep two versions of jsons. Another way is to use a library to create the json.</p>
  <p>First I tried the <a href="https://www.powershellgallery.com/packages/newtonsoft.json/1.0.1.2" rel="nofollow noreferrer">Newtonsoft-Json</a> powershell module, but it just <a href="https://stackoverflow.com/questions/64189421/what-is-the-parameterizedproperty-chars-property-on-the-string-type-added-there#64189421">does not work</a>. I think the problem is that whatever C# library we use, it must be aware of <code>PSCustomObject</code> and alike and treat them specially. So, we cannot just take any C# JSON library.</p>
  <p>At this point I am left with having two jsons - one per PS edition, which is kind of sad.</p>
  <p>Are there better options?</p>
  <p><strong>EDIT 1</strong></p>
  <p>I guess I can always read the json, convert to object and then back to json again. That sucks.</p>
  <p><strong>EDIT 2</strong></p>
  <p>I tried to use <code>ConvertTo-Json -Compress</code>. This eliminates the difference in spacing, but the problem is that for some reason the desktop version translates all the non characters to <code>\u000...</code> representation. The core version does not do it.</p>
  <p>Please, observe:</p>
  <p><strong>Desktop</strong></p>
  <pre><code>C:\&gt; @{ x = &quot;'a'&quot; } |ConvertTo-Json -Compress
  {&quot;x&quot;:&quot;\u0027a\u0027&quot;}
  C:\&gt;
  </code></pre>
  <p><strong>Core</strong></p>
  <pre><code>C:\&gt;  @{ x = &quot;'a'&quot; } |ConvertTo-Json -Compress
  {&quot;x&quot;:&quot;'a'&quot;}
  C:\&gt;
  </code></pre>
  <p>Now the core version has the flag <code>-EscapeHandling</code>, so:</p>
  <pre><code>C:\&gt;  @{ x = &quot;'a'&quot; } |ConvertTo-Json -Compress -EscapeHandling EscapeHtml
  {&quot;x&quot;:&quot;\u0027a\u0027&quot;}
  C:\&gt;
  </code></pre>
  <p>Bingo! Same result. But now this code does not run on the desktop version, which does not have this flag. More massaging is needed. I will check if that is the only problem.</p>
  <p><strong>EDIT 3</strong></p>
  <p>It is impossible to reconcile the differences between the core and the desktop versions without expensive post processing. Please, observe:</p>
  <p><strong>Desktop</strong></p>
  <pre><code>C:\&gt; @{ x = '&quot;a&quot;';y = &quot;'b'&quot; } |ConvertTo-Json -Compress
  {&quot;y&quot;:&quot;\u0027b\u0027&quot;,&quot;x&quot;:&quot;\&quot;a\&quot;&quot;}
  C:\&gt;
  </code></pre>
  <p><strong>Core</strong></p>
  <pre><code>C:\&gt; @{ x = '&quot;a&quot;';y = &quot;'b'&quot; } |ConvertTo-Json -Compress -EscapeHandling EscapeHtml
  {&quot;y&quot;:&quot;\u0027b\u0027&quot;,&quot;x&quot;:&quot;\u0022a\u0022&quot;}
  C:\&gt; @{ x = '&quot;a&quot;';y = &quot;'b'&quot; } |ConvertTo-Json -Compress
  {&quot;y&quot;:&quot;'b'&quot;,&quot;x&quot;:&quot;\&quot;a\&quot;&quot;}
  C:\&gt;
  </code></pre>
  <p>Any suggestions on how to salvage the json approach?</p>
  <p><strong>EDIT 4</strong></p>
  <p>The <code>Export-CliXml</code> approach does not work too, because of the differences between the PS versions.</p>
  <p><strong>Desktop</strong></p>
  <pre><code>C:\&gt; ('{a:1}' | ConvertFrom-Json).a.gettype()
  
  IsPublic IsSerial Name                                     BaseType
  -------- -------- ----                                     --------
  True     True     Int32                                    System.ValueType
  
  
  C:\&gt;
  </code></pre>
  <p><strong>Core</strong></p>
  <pre><code>C:\&gt; ('{a:1}' | ConvertFrom-Json).a.gettype()
  
  IsPublic IsSerial Name                                     BaseType
  -------- -------- ----                                     --------
  True     True     Int64                                    System.ValueType
  
  C:\&gt;
  </code></pre>
  <p>So the same JSON is represented using different numeric types - <code>Int32</code> in desktop and <code>Int64</code> in core. That puts to bed the option of using <code>Export-CliXml</code>.</p>
  <p>Unless I am missing something.</p>
  <p>I believe there is no other choice, but do the double conversion - <strong>json -&gt; object -&gt; json</strong> and then I will have two jsons created on the same PS edition. That sucks big time.</p>