2012-08-03 76 views
2

在德爾福XE2,我需要做一個函數,收到JSONValue並返回一個縮進String,很像JSONLint。這個JSONValue可以是任何類型的JSON,可以是數組,對象,甚至只是一個字符串,所以我必須確保使用此函數覆蓋所有類型。我不知道從哪裏開始。JSONValue縮進字符串

+0

你想漂亮地打印json字符串嗎? – 2012-08-03 14:22:28

+0

基本上,是的。 – bpromas 2012-08-03 14:25:02

回答

4

您必須遞歸執行此操作。類似這樣的:

const INDENT_SIZE = 2; 

procedure PrettyPrintJSON(value: TJSONValue; output: TStrings; indent: integer = 0); forward; 

procedure PrettyPrintPair(value: TJSONPair; output: TStrings; last: boolean; indent: integer); 
const TEMPLATE = '%s : %s'; 
var 
    line: string; 
    newList: TStringList; 
begin 
    newList := TStringList.Create; 
    try 
    PrettyPrintJSON(value.JsonValue, newList, indent); 
    line := format(TEMPLATE, [value.JsonString.ToString, Trim(newList.Text)]); 
    finally 
    newList.Free; 
    end; 

    line := StringOfChar(' ', indent * INDENT_SIZE) + line; 
    if not last then 
    line := line + ',' 
    output.add(line); 
end; 

procedure PrettyPrintJSON(value: TJSONValue; output: TStrings; indent: integer); 
var 
    i: integer; 
begin 
    if value is TJSONObject then 
    begin 
    output.add(StringOfChar(' ', indent * INDENT_SIZE) + '{'); 
    for i := 0 to TJSONObject(value).size - 1 do 
     PrettyPrintPair(TJSONObject(value).Get(i), output, i = TJSONObject(value).size - 1, indent + 1); 
    output.add(StringOfChar(' ', indent * INDENT_SIZE) + '}'); 
    end 
    else if value is TJSONArray then 
    //left as an exercise to the reader 
    else output.add(StringOfChar(' ', indent * INDENT_SIZE) + value.ToString); 
end; 

這涵蓋了基本原理。警告:我把它寫在我頭頂。它可能不正確,甚至不能編譯,但它是一般的想法。此外,你必須拿出你自己的打印JSON數組的實現。但是這應該讓你開始。

2

我採納了梅森的代碼,做讀者的運動,並把它放在一個單獨的單元:

unit uJSONTools; 

interface 

Uses 
    Classes, SysUtils, DBXJSON; 

procedure PrettyPrintJSON(JSONValue: TJSONValue; OutputStrings: TStrings; indent: integer = 0); 
// Formats JSONValue to an indented structure and adds it to OutputStrings 

implementation 

const INDENT_SIZE = 2; 

procedure PrettyPrintPair(JSONValue: TJSONPair; OutputStrings: TStrings; last: boolean; indent: integer); 
const TEMPLATE = '%s : %s'; 
var 
    line: string; 
    newList: TStringList; 
begin 
    newList := TStringList.Create; 
    try 
    PrettyPrintJSON(JSONValue.JsonValue, newList, indent); 
    line := format(TEMPLATE, [JSONValue.JsonString.ToString, Trim(newList.Text)]); 
    finally 
    newList.Free; 
    end; 

    line := StringOfChar(' ', indent * INDENT_SIZE) + line; 
    if not last then 
    line := line + ','; 
    OutputStrings.add(line); 
end; 

procedure PrettyPrintArray(JSONValue: TJSONArray; OutputStrings: TStrings; last: boolean; indent: integer); 
var i: integer; 
begin 
    OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + '['); 
    for i := 0 to JSONValue.size - 1 do 
     PrettyPrintJSON(JSONValue.Get(i), OutputStrings, indent + 1); 
    OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + ']'); 
end; 

procedure PrettyPrintJSON(JSONValue: TJSONValue; OutputStrings: TStrings; indent: integer = 0); 
var 
    i: integer; 
begin 
    if JSONValue is TJSONObject then 
    begin 
    OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + '{'); 
    for i := 0 to TJSONObject(JSONValue).size - 1 do 
     PrettyPrintPair(TJSONObject(JSONValue).Get(i), OutputStrings, i = TJSONObject(JSONValue).size - 1, indent + 1); 
    OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + '}'); 
    end 
    else if JSONValue is TJSONArray then 
    PrettyPrintArray(TJSONArray(JSONValue), OutputStrings, i = TJSONObject(JSONValue).size - 1, indent + 1) 
    else OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + JSONValue.ToString); 
end; 

end. 
+0

代碼似乎錯過了數組中對象之間的逗號。 – rhody 2014-08-07 21:52:59

1

增加由Doggen和惠勒答案,我更換了PrettyPrintArray日常用以下替換爲了確保數組對象以逗號分隔,否則相紙輸出是無效的json。

procedure PrettyPrintArray(JSONValue: TJSONArray; OutputStrings: TStrings; last:  boolean; indent: integer); 
var i: integer; 
begin 
    OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + '['); 
    for i := 0 to JSONValue.size - 1 do 
     begin 
     PrettyPrintJSON(JSONValue.Get(i), OutputStrings, indent + 1); 
     if i < JSONValue.size - 1 then 
     OutputStrings[OutputStrings.Count-1] := OutputStrings[OutputStrings.Count-1] + ','; 
     end; 
    OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + ']'); 
end;