我無法轉換字符串轉義字符到和從 a TJsonString。 (我正在使用Delphi XE 2,更新4,修補程序1)。如何使用DBXJSON將字符串與帶有轉義/特殊字符的JSON轉換?
注:我熟悉SuperObject,但我的要求是使用DBXJSON單元。
看起來TJSONString在通過ToString()方法返回JSON表示時沒有正確轉義。
我做錯了什麼(如果有的話),我如何正確地將字符串轉換爲正確的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
編輯:
事實證明,下面的例子確如預期工作。
是什麼我也不清楚的是,當通過它的構造函數創建一個和TJSONString將其添加到TJSONObject的ToString()方法會返回一個逃脫表示。但是,在解析後得到一個TJSONObject,ToString()方法將返回未經轉義的表示。
唯一的其他警告是下面示例代碼中的EscapeString()函數處理雙引號。雖然我沒有在這裏使用雙引號,但是我的其他一些代碼是,並且導致解析失敗,因爲TJSONString已經轉義了該字符。我已經更新了我的示例代碼,以從EscapeString()函數中刪除此處理,這是我在自己的類中使用的。
再次感謝@Linas的答案,這幫助我「得到」它。
原始字符串值:
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"}
解析聯合國轉義文本失敗:
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"}
解析轉義文本形式(無效)(文本解析與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_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 (") 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) < 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: ', 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.
感謝@Linas,但我能夠做自己逃脫按我的示例代碼。另一個問題是,當TJsonObject包含轉義字符串時,似乎無法正確解析JSON字符串。我希望這仍然是我做錯了事。 :) – Doug 2012-08-02 23:13:08
@Doug只用Delphi XE測試過,一切都按預期工作。您可能以錯誤的方式解析json字符串。看到我的答案編輯它應該如何完成。 – Linas 2012-08-03 06:57:32
謝謝@Linas。在更詳細地檢查我的代碼後,我發現我的轉義例程是處理雙引號(\「)。問題是TJSONString已經處理了這種情況,並最終添加了一個額外的轉義符(\\」),解析失敗。刪除這種情況後,一切正常。我已更新我的示例來解決此問題。 – Doug 2012-08-06 17:02:30