mirror of
https://github.com/keymanapp/keyman.git
synced 2026-08-11 11:25:34 +00:00
157 lines
4.5 KiB
ObjectPascal
157 lines
4.5 KiB
ObjectPascal
(*
|
|
Name: JsonUtil
|
|
Copyright: Copyright (C) SIL International.
|
|
Documentation:
|
|
Description:
|
|
Create Date: 10 Oct 2014
|
|
|
|
Modified Date: 30 May 2015
|
|
Authors: mcdurdin
|
|
Related Files:
|
|
Dependencies:
|
|
|
|
Bugs:
|
|
Todo:
|
|
Notes:
|
|
History: 10 Oct 2014 - mcdurdin - I4440 - V9.0 - If more than one language listed for a keyboard, the JSON file becomes invalid
|
|
30 May 2015 - mcdurdin - I4727 - Changing font while touch layout editor in Code mode results in broken \ rules
|
|
*)
|
|
unit JsonUtil;
|
|
|
|
interface
|
|
|
|
uses
|
|
System.JSON,
|
|
System.Classes,
|
|
System.Generics.Collections;
|
|
|
|
function JSONToString(obj: TJSONAncestor; ReplaceSlashes: Boolean = False): string;
|
|
|
|
// Formats JSONValue to an indented structure and adds it to OutputStrings
|
|
procedure PrettyPrintJSON(JSONValue: TJSONValue; OutputStrings: TStrings; indent: integer = 0);
|
|
function ParseJSONValue(const Data: string; var Offset: Integer): TJSONObject; // I4035 // I4260
|
|
function JSONDateToDateTime(const Value: string; var DateTime: TDateTime): Boolean;
|
|
function DateTimeToJSONDate(ADateTime: TDateTime): string;
|
|
function LoadJSONFromFile(const Filename: string; var Offset: Integer): TJSONObject;
|
|
|
|
implementation
|
|
|
|
uses
|
|
System.DateUtils,
|
|
System.StrUtils,
|
|
System.SysUtils;
|
|
|
|
function JSONToString(obj: TJSONAncestor; ReplaceSlashes: Boolean = False): string;
|
|
var
|
|
bytes: TBytes;
|
|
len: Integer;
|
|
begin
|
|
SetLength(bytes, obj.EstimatedByteSize);
|
|
len := obj.ToBytes(bytes, 0);
|
|
Result := TEncoding.UTF8.GetString(bytes, 0, len);
|
|
if ReplaceSlashes then
|
|
Result := ReplaceStr(Result, '\/', '/');
|
|
end;
|
|
|
|
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.Count - 1 do
|
|
begin
|
|
PrettyPrintJSON(JSONValue.Items[i], OutputStrings, indent);
|
|
if i < JSONValue.Count - 1 then
|
|
OutputStrings[OutputStrings.Count-1] := OutputStrings[OutputStrings.Count-1] + ','; // I4440
|
|
end;
|
|
OutputStrings.add(StringOfChar(' ', (indent-1) * 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).Count - 1 do
|
|
PrettyPrintPair(TJSONObject(JSONValue).Pairs[i], OutputStrings, i = TJSONObject(JSONValue).Count - 1, indent + 1);
|
|
OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + '}');
|
|
end
|
|
else if JSONValue is TJSONArray then
|
|
PrettyPrintArray(TJSONArray(JSONValue), OutputStrings, True, indent + 1)
|
|
else
|
|
OutputStrings.add(StringOfChar(' ', indent * INDENT_SIZE) + JSONToString(JSONValue, True)); // I4727
|
|
end;
|
|
|
|
function RemoveWhites(const str1: string): string;
|
|
var
|
|
ch: char;
|
|
inQuotes: Boolean;
|
|
begin
|
|
Result := '';
|
|
inQuotes := False;
|
|
for ch in str1 do
|
|
begin
|
|
if ch = '"' then
|
|
inQuotes := not inQuotes;
|
|
if InQuotes or not CharInSet(ch, [' ',#9,#10,#13]) then
|
|
Result := Result + ch;
|
|
end;
|
|
end;
|
|
|
|
function ParseJSONValue(const Data: string; var Offset: Integer): TJSONObject; // I4035 // I4260
|
|
var
|
|
UTF8Data: TBytes;
|
|
begin
|
|
UTF8Data := TEncoding.UTF8.GetBytes(RemoveWhites(Data));
|
|
Result := TJSONObject.ParseJSONValue(UTF8Data, Offset, True) as TJSONObject; // I4083
|
|
end;
|
|
|
|
function JSONDateToDateTime(const Value: string; var DateTime: TDateTime): Boolean;
|
|
begin
|
|
Result := TryISO8601ToDate(Value, DateTime, False);
|
|
end;
|
|
|
|
function DateTimeToJSONDate(ADateTime: TDateTime): string;
|
|
begin
|
|
Result := DateToISO8601(ADateTime, False);
|
|
end;
|
|
|
|
function LoadJSONFromFile(const Filename: string; var Offset: Integer): TJSONObject;
|
|
var
|
|
ss: TStringStream;
|
|
begin
|
|
ss := TStringStream.Create('', TEncoding.UTF8);
|
|
try
|
|
ss.LoadFromFile(Filename);
|
|
offset := 0;
|
|
Result := ParseJSONValue(ss.DataString, offset);
|
|
finally
|
|
ss.Free;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|