使用DBXJSON如何使用转义/特殊字符将字符串转换为JSON?

前端之家收集整理的这篇文章主要介绍了使用DBXJSON如何使用转义/特殊字符将字符串转换为JSON?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
将转义字符串转换为TJsonString和/或从TJsonString转换失败的问题. (我使用的是Delphi XE 2,Update 4,Hotfix 1).

注意:我熟悉SuperObject,但我的要求是使用DBXJSON单元.

当通过ToString()方法返回JSON表示时,TJSONString看起来不正确地转义.

什么(如果有的话)我做错了,如何正确地将一个字符串转换为/从正确的JSON表示的特殊字符?

也许我错过了一些事情,但是以下问答似乎都没有直接解决这个问题:

> Delphi decode json/utf8 escaped text
> Delphi JSON library for XE2 available for object serialization
> Delphi: JSON array
> How to parse nested JSON object in Delphi XE2?
> Nested json object deserializing using Delphi 2012

EDIT:

As it turns out,the examples below were indeed working as expected.

What wasn’t clear to me was that when creating a TJSONString via it’s constructor and adding it to a TJSONObject,the ToString() method will return an escaped representation. However,after parsing a TJSONObject,the ToString() method will returned the un-escaped representation.

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.

Thanks again to @Linas for the answer,which helped me to “get” it.

原始字符串值:

Text := 'c:\path\name' +#13 + #10 + 'Next Line';

Text: c:\path\name
Next Line

什么DBXJSON生产(NO ESCAPES):

JsonString: "c:\path\name
Next Line"

JsonPair: "MyString":"c:\path\name
Next Line"

JsonObject: {"MyString":"c:\path\name
Next Line"}

解析UN-escaped文本失败:

Text to parse: {"MyString":"c:\path\name
Next Line"}

Parsed JsonObject = *NIL*

我期待DBXJSON生产:

Escaped String: c:\\path\\name\r\nNext Line

JsonString: "c:\\path\\name\r\nNext Line"

JsonPair: "MyString":"c:\\path\\name\r\nNext Line"

JsonObject: {"MyString":"c:\\path\\name\r\nNext Line"}

解析ESCAPED文本(INVALID)(要解析的文本为JSONLint):

Text to parse: {"MyString":"c:\\path\\name\r\nNext Line"}

Parsed JsonObject.ToString(): {"MyString":"c:\path\name
Next Line"}

我注意到TJSONString似乎正确处理的唯一特殊字符是双引号(“).

以下是我使用的代码

program JsonTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,DbxJson;

function EscapeString(const AValue: string): string;
const
  ESCAPE = '\';
  // QUOTATION_MARK = '"';
  REVERSE_SOLIDUS = '\';
  SOLIDUS = '/';
  BACKSPACE = #8;
  FORM_@R_301_349@ = #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 (") 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_@R_301_349@: 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) < 32) or (Integer(AChar) > 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: ',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.

解决方法

您可以尝试定义自己的TJSONString类型并在那里转义json字符串.例如.:
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,AIndex + 6,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',ix);
      end;
      #9:
      begin
        AddChars('\t',ix);
      end;
      #10:
      begin
        AddChars('\n',ix);
      end;
      #12:
      begin
        AddChars('\f',ix);
      end;
      #13:
      begin
        AddChars('\r',ix);
      end;
      #0 .. #7,#11,#14 .. #31:
      begin
        AddUnicodeChars('\u' + IntToHex(Word(AChar),4),ix);
      end
      else
      begin
        if Word(AChar) > 127 then
        begin
          AddUnicodeChars('\u' + IntToHex(Word(AChar),ix);
        end
        else
        begin
          Inc(ix);
        end;
      end;
    end;
  end;
end;

用法示例:

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;

这就是解析应该如何做:

//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;

猜你在找的JavaScript相关文章