How do I convert a string to and from JSON with escaped/special characters using DBXJSON?

You can try to define your own TJSONString type and escape json strings there. E.g.:

uses
  DBXJSON;

type
  TSvJsonString = class(TJSONString)
  private
    function EscapeValue(const AValue: string): string;
  public
    constructor Create(const AValue: string); overload;
  end;

{ TSvJsonString }

constructor TSvJsonString.Create(const AValue: string);
begin
  inherited Create(EscapeValue(AValue));
end;

function TSvJsonString.EscapeValue(const AValue: string): string;

  procedure AddChars(const AChars: string; var Dest: string; var AIndex: Integer); inline;
  begin
    System.Insert(AChars, Dest, AIndex);
    System.Delete(Dest, AIndex + 2, 1);
    Inc(AIndex, 2);
  end;

  procedure AddUnicodeChars(const AChars: string; var Dest: string; var AIndex: Integer); inline;
  begin
    System.Insert(AChars, Dest, AIndex);
    System.Delete(Dest, AIndex + 6, 1);
    Inc(AIndex, 6);
  end;

var
  i, ix: Integer;
  AChar: Char;
begin
  Result := AValue;
  ix := 1;
  for i := 1 to System.Length(AValue) do
  begin
    AChar :=  AValue[i];
    case AChar of
      '/', '\', '"':
      begin
        System.Insert('\', Result, ix);
        Inc(ix, 2);
      end;
      #8:  //backspace \b
      begin
        AddChars('\b', Result, ix);
      end;
      #9:
      begin
        AddChars('\t', Result, ix);
      end;
      #10:
      begin
        AddChars('\n', Result, ix);
      end;
      #12:
      begin
        AddChars('\f', Result, ix);
      end;
      #13:
      begin
        AddChars('\r', Result, ix);
      end;
      #0 .. #7, #11, #14 .. #31:
      begin
        AddUnicodeChars('\u' + IntToHex(Word(AChar), 4), Result, ix);
      end
      else
      begin
        if Word(AChar) > 127 then
        begin
          AddUnicodeChars('\u' + IntToHex(Word(AChar), 4), Result, ix);
        end
        else
        begin
          Inc(ix);
        end;
      end;
    end;
  end;
end;

Usage example:

procedure Test;
var
  LText, LEscapedText: string;
  LJsonString: TSvJsonString;
  LJsonPair: TJsonPair;
  LJsonObject: TJsonObject;
begin
  LText := 'c:\path\name' + #13 + #10 + 'Next Line';
  LJsonString := TSvJsonString.Create(LText);
  LJsonPair := TJsonPair.Create('MyString', LJsonString);
  LJsonObject := TJsonObject.Create(LJsonPair);
  try
    LEscapedText := LJsonObject.ToString;
    //LEscapedText is: c:\\path\\name\r\nNext Line
  finally
    LJsonObject.Free;
  end;
end;

And this is how parsing should be done:

//AText := '{"MyString":"c:\\path\\name\r\nNext Line"}';
function Parse(const AText: string): string;
var
  obj: TJSONValue;
begin
  obj := TJSONObject.ParseJSONValue(AText);
  try
    Result := obj.ToString;
    //Result := {"MyString":"c:\path\name
   //Next Line"}
  finally
    obj.Free;
  end;
end;

We just ran into this lovely problem, where our backslashes weren't being escaped (but our double quotes were, apparently lol)...

The solution was to stop using TJSONObject.ToString(), and use TJSONObject.ToJSON() instead. This gives you the correctly escaped string, as opposed to the human readable format that ToString() returns.

Hope this helps someone :)