title: How do I convert a string to and from JSON with escaped/special characters using DBXJSON?
body: <p>I'm having trouble converting a string with escaped characters <strong>to</strong> and <strong>from</strong> a TJsonString. (I'm using Delphi XE 2, Update 4, Hotfix 1).</p>
  <p>NOTE: I am familiar with the <a href="http://www.progdigy.com/?page_id=6" rel="noreferrer">SuperObject</a>, but my requirements are to use the DBXJSON unit.</p>
  <p>It looks like the TJSONString is not correctly escaped when returning the JSON representation via the ToString() method.</p>
  <p><strong>What (if anything) am I doing wrong and how do I correctly convert a string with special characters to/from its correct JSON representation?</strong></p>
  <p>Perhaps I missed something, but none of the following Q&amp;As seemed to address this directly:</p>
  <ul>
  <li><a href="https://stackoverflow.com/questions/9713491/delphi-decode-json-utf8-escaped-text">Delphi decode json/utf8 escaped text</a></li>
  <li><a href="https://stackoverflow.com/questions/7731833/delphi-json-library-for-xe2-available-for-object-serialization">Delphi JSON library for XE2 available for object serialization</a></li>
  <li><a href="https://stackoverflow.com/questions/10549935/delphi-json-array">Delphi: JSON array</a></li>
  <li><a href="https://stackoverflow.com/questions/10808912/how-to-parse-nested-json-object-in-delphi-xe2">How to parse nested JSON object in Delphi XE2?</a></li>
  <li><a href="https://stackoverflow.com/questions/10559080/nested-json-object-deserializing-using-delphi-2012">Nested json object deserializing using Delphi 2012</a></li>
  </ul>
  <blockquote>
  <p><strong>EDIT:</strong></p>
  <p>As it turns out, the examples below were indeed working as expected.</p>
  <p>What wasn't clear to me was that when <strong>creating</strong> a TJSONString via it's constructor    and adding it to a TJSONObject, the ToString() method will return an <strong>escaped</strong>    representation.  However, after <strong>parsing</strong> a TJSONObject, the ToString() method will    returned the <strong>un-escaped</strong> representation.</p>
  <p>The only other caveat was that the EscapeString() function in the sample code below was handling the double-quote.  Although I wasn't using the double quote here, some of my other code was, and that caused the parsing to fail because TJSONString already escapes that character.  I've updated my sample code to remove this handling from the EscapeString() function, which is what I've been using in my own classes.</p>
  <p>Thanks again to @Linas for the answer, which helped me to &quot;get&quot; it.</p>
  </blockquote>
  <p><strong>Raw String Value:</strong></p>
  <pre><code>Text := 'c:\path\name' +#13 + #10 + 'Next Line';
  
  Text: c:\path\name
  Next Line
  </code></pre>
  <p><strong>What DBXJSON produces (NO ESCAPES):</strong></p>
  <pre><code>JsonString: &quot;c:\path\name
  Next Line&quot;
  
  JsonPair: &quot;MyString&quot;:&quot;c:\path\name
  Next Line&quot;
  
  JsonObject: {&quot;MyString&quot;:&quot;c:\path\name
  Next Line&quot;}
  </code></pre>
  <p><strong>Parsing UN-escaped Text <em>FAILS</em>:</strong></p>
  <pre><code>Text to parse: {&quot;MyString&quot;:&quot;c:\path\name
  Next Line&quot;}
  
  Parsed JsonObject = *NIL*
  </code></pre>
  <p><strong>What I <em>EXPECT</em> DBXJSON to produce:</strong></p>
  <pre><code>Escaped String: c:\\path\\name\r\nNext Line
  
  JsonString: &quot;c:\\path\\name\r\nNext Line&quot;
  
  JsonPair: &quot;MyString&quot;:&quot;c:\\path\\name\r\nNext Line&quot;
  
  JsonObject: {&quot;MyString&quot;:&quot;c:\\path\\name\r\nNext Line&quot;}
  </code></pre>
  <p><strong>Parsing ESCAPED Text (<em>INVALID</em>) (Text to parse validated with <a href="http://jsonlint.com/" rel="noreferrer">JSONLint</a>):</strong></p>
  <pre><code>Text to parse: {&quot;MyString&quot;:&quot;c:\\path\\name\r\nNext Line&quot;}
  
  Parsed JsonObject.ToString(): {&quot;MyString&quot;:&quot;c:\path\name
  Next Line&quot;}
  </code></pre>
  <p><em><strong>I've noticed that the only special character TJSONString seems to process correctly is the double quote (&quot;).</strong></em></p>
  <p>Here is the code I'm using:</p>
  <pre><code>program JsonTest;
  
  {$APPTYPE CONSOLE}
  
  {$R *.res}
  
  uses
    System.SysUtils, DbxJson;
  
  function EscapeString(const AValue: string): string;
  const
    ESCAPE = '\';
    // QUOTATION_MARK = '&quot;';
    REVERSE_SOLIDUS = '\';
    SOLIDUS = '/';
    BACKSPACE = #8;
    FORM_FEED = #12;
    NEW_LINE = #10;
    CARRIAGE_RETURN = #13;
    HORIZONTAL_TAB = #9;
  var
    AChar: Char;
  begin
    Result := '';
    for AChar in AValue do
    begin
      case AChar of
        // !! Double quote (&quot;) is handled by TJSONString
        // QUOTATION_MARK: Result := Result + ESCAPE + QUOTATION_MARK;
        REVERSE_SOLIDUS: Result := Result + ESCAPE + REVERSE_SOLIDUS;
        SOLIDUS: Result := Result + ESCAPE + SOLIDUS;
        BACKSPACE: Result := Result + ESCAPE + 'b';
        FORM_FEED: Result := Result + ESCAPE + 'f';
        NEW_LINE: Result := Result + ESCAPE + 'n';
        CARRIAGE_RETURN: Result := Result + ESCAPE + 'r';
        HORIZONTAL_TAB: Result := Result + ESCAPE + 't';
        else
        begin
          if (Integer(AChar) &lt; 32) or (Integer(AChar) &gt; 126) then
            Result := Result + ESCAPE + 'u' + IntToHex(Integer(AChar), 4)
          else
            Result := Result + AChar;
        end;
      end;
    end;
  end;
  
  procedure Test;
  var
    Text: string;
    JsonString: TJsonString;
    JsonPair: TJsonPair;
    JsonObject: TJsonObject;
  begin
    try
      Writeln('Raw String Value');
      Writeln('-----------------');
      Text := 'c:\path\name' +#13 + #10 + 'Next Line';
      Writeln('Text: ', Text);
      JsonString := TJsonString.Create(Text);
      JsonPair := TJsonPair.Create('MyString', JsonString);
      JsonObject := TJsonObject.Create(JsonPair);
      // DBXJSON results
      Writeln;
      Writeln('What DBXJSON produces');
      Writeln('---------------------');
      Writeln('JsonString: ', JsonString.ToString);
      Writeln;
      Writeln('JsonPair: ', JsonPair.ToString);
      Writeln;
      Writeln('JsonObject: ', JsonObject.ToString);
      Writeln;
  
      // assign JSON representation
      Text := JsonObject.ToString;
      // free json object
      JsonObject.Free;
      // parse it
      JsonObject:= TJsonObject.ParseJsonValue(TEncoding.ASCII.GetBytes(
        Text), 0) as TJsonObject;
      Writeln('Parsing UN-escaped Text *FAILS* ');
      Writeln('----------------------------------');
      Writeln('Text to parse: ', Text);
      Writeln;
      if (JsonObject = nil) then
        Writeln('Parsed JsonObject = *NIL*')
      else
        Writeln('Parsed JsonObject: ', JsonObject.ToString);
      Writeln;
      // free json object
      JsonObject.Free;
      // expected results
      Text := 'c:\path\name' +#13 + #10 + 'Next Line';
      Text := EscapeString(Text);
      JsonString := TJsonString.Create(Text);
      JsonPair := TJsonPair.Create('MyString', JsonString);
      JsonObject := TJsonObject.Create(JsonPair);
      Writeln('What I *EXPECT* DBXJSON to produce');
      Writeln('----------------------------------');
      Writeln('Escaped String: ', Text);
      Writeln;
      Writeln('JsonString: ', JsonString.ToString);
      Writeln;
      Writeln('JsonPair: ', JsonPair.ToString);
      Writeln;
      Writeln('JsonObject: ', JsonObject.ToString);
      Writeln;
      // assign JSON representation
      Text := JsonObject.ToString;
      // free json object
      JsonObject.Free;
      // parse it
      JsonObject:= TJsonObject.ParseJsonValue(TEncoding.ASCII.GetBytes(
        Text), 0) as TJsonObject;
      Writeln('Parsing ESCAPED Text (*INVALID*) ');
      Writeln('----------------------------------');
      Writeln('Text to parse: ', Text);
      Writeln;
      Writeln('Parsed JsonObject.ToString(): ', JsonObject.ToString);
      Writeln;
      Readln;
    except
      on E: Exception do
      begin
        Writeln(E.ClassName, ': ', E.Message);
        Readln;
      end;
    end;
  end;
  
  begin
    Test;
  end.
  </code></pre>