Reputation: 919
I am looking for a function that will take a string of JSON as input and format it with line breaks and indentations (tabs).
Example: I have input line:
{"menu": {"header": "JSON viewer", "items": [{"id": "Delphi"},{"id": "Pascal", "label": "Nice tree format"}, null]}}
And want to get a readable result as text:
{
"menu":{
"header":"JSON viewer",
"items":[
{
"id":"Delphi"
},
{
"id":"Pascal",
"label":"Nice tree format"
},
null
]
}
}
I found a lot of examples for PHP and C#, but not for Delphi. Could someone help with such a function?
Update - Solution with SuperObject:
function FormatJson (InString: WideString): string; // Input string is "InString"
var
Json : ISuperObject;
begin
Json := TSuperObject.ParseString(PWideChar(InString), True);
Result := Json.AsJson(true, false); //Here comes your result: pretty-print JSON
end;
Upvotes: 18
Views: 20867
Reputation: 111
Since Delphi 10.3 Rio, no REST.Json
required:
function Format_JSON(Value: String; Indentation: Integer = 4): String; inline;
var
JV: TJSONValue; // not TJSONObject
begin
JV := nil;
try
try
JV := TJSONObject.ParseJSONValue(Value);
// TJSONObject.ParseJSONValue(Value) as TJSONObject cast fails
Result := JV.Format(Indentation);
except
on E: Exception do Log_Exception(E);
end;
finally
FreeAndNil(JV);
end;
end;
Upvotes: 1
Reputation: 108
This is a bit old, but if anyone is interested Delphi's native System.JSON unit can do this too. Sample uses a TMemo and a TButton to format the JSON
procedure TForm1.btnFormatJSONClick(Sender: TObject);
const
DEF_INDENT = 2;
var
JO : TJSONObject;
begin
try
JO := TJSONObject.ParseJSONValue(memoJSON.Text) as TJSONObject;
memoJSON.Text := JO.Format(DEF_INDENT);
except
on E:Exception do
begin
MessageDlg('Error in JSON syntax', mtError, [mbOK], 0);
end;
end;
end;
Upvotes: 5
Reputation: 2510
If you do not want to use any external library, and you're using a delphi XE5 or newer, there is a very handy TJson.Format()
function in the REST.Json
unit.
uses json, REST.Json;
{ ... }
function FormatJSON(json: String): String;
var
tmpJson: TJsonObject;
begin
tmpJson := TJSONObject.ParseJSONValue(json);
Result := TJson.Format(tmpJson);
FreeAndNil(tmpJson);
end;
Upvotes: 21
Reputation: 43023
You may also use the following methods of our Open Source SynCommons.pas
unit:
var json,new: RawUTF8;
begin
json := '{"menu": {"header": "JSON viewer", "items": [{"id": "Delphi"},{"id": "Pascal", "label": "Nice tree format"}, null]}}';
new := JSONReformat(json,jsonHumanReadable);
...
Here new
will contain:
{
"menu": {
"header": "JSON viewer",
"items":
[
{
"id": "Delphi"
},
{
"id": "Pascal",
"label": "Nice tree format"
},
null
]
}
}
If you use the jsonUnquotedPropName
format:
new := JSONReformat(json,jsonUnquotedPropName);
you will get the following extended syntax (similar to the one used in JavaScript or MongoDB shell):
{
menu: {
header: "JSON viewer",
items:
[
{
id: "Delphi"
},
{
id: "Pascal",
label: "Nice tree format"
},
null
]
}
}
This syntax is accepted as valid input for all the JSON functions of our Open Source framework, as alternative to the default JSON syntax. We found it pretty useful, e.g. for configuration files.
Note that our JSONReformat()
function is very fast. It converts the huge 190 MB of unconformatable JSON content from CityLots into 400 MB of beautified JSON (intended and with line fields) in 1.4 seconds. SuperObject is just able to read it in 10 seconds, and uses 1.1 GB just for storing the 190 MB of content. And DBXJSON is not even able to load the data: it consumes all 32 bit memory - under Win64 (XE6), it takes 50 seconds and uses 3 GB of RAM to read the 190 MB of JSON. See this article for some numbers.
Upvotes: 9
Reputation: 380
If you're working with Delphi XE or newer, you can use the delphi-xe-json library
function PrettyPrint (aJSON : string) : string;
var
jo : IJSONObject
begin
jo := TJSON.NewObject(aJSON);
result := jo.ToString(true);
end;
Upvotes: 1
Reputation: 9096
Use the superobject library, make sure that you use the latest version from the repository file, not the 1.2.4 ZIP.
Then you can format your TSuperObject object with .AsJSON(true)
(the 'true' does the trick).
[ Note that you have no control over the order in which the JSON fields are displayed ]
[ And to create your object from the string: var lJSON : ISuperObject; lJSON := SO(string);
]
Upvotes: 7