#json #delphi #delphi-xe4
#json #delphi #delphi-xe4
Вопрос:
Я боролся с этим некоторое время, и выполнение чего-то простого, кажется, занимает слишком много времени.
У меня есть такой файл, как этот:
[
{
"FirstName": "Oleg",
"Surname": "Buckley"
},
{
"FirstName": "Amery",
"Surname": "Mcmillan"
},
{
"FirstName": "Denton",
"Surname": "Burnett"
....
Я хочу иметь возможность включить их в свою программу. До сих пор я работал над этой милой маленькой функцией:
function GetGeneratedNames: TArray<string>;
var fileName: TFileName;
JSONValue, jv: TJSONValue;
JSONArray: TJSONArray;
jo: TJSONObject;
pair: TJSONPair;
begin
result := nil;
filename := ExePath 'Names.json';
JSONValue := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(TFile.ReadAllText(filename)), 0);
if JSONValue is TJSONArray then begin
for jv in (JSONValue as TJSONArray) do begin
if jv is TJSONObject then begin
jo := jv as TJSONObject;
for pair in jo do begin
Append(result, jo.Value);
end;
end;
end;
end;
end{ GetGeneratedNames};
Проблема в том, что он возвращает массив пустых строк. Кто-нибудь может указать мне правильное направление?
ТИА Марк
Комментарии:
1. Попробуйте использовать
SuperObject
вместо этого — это на целый мир проще.2.
SuperObject
было бы так же просто, какO.AsArray[jv].S['FirstName']
иO.AsArray[jv].S['Surname']
3. Не могли бы вы выразиться более конкретно? Что вы подразумеваете под суперобъектом? Я не могу найти его в источнике Embardcadero.
4. Это потому, что он не является частью исходного кода Embarcadero, это сторонняя библиотека
Ответ №1:
// XE5- version
uses System.SysUtils, Data.DBXJSON, System.IOUtils;
function GetGeneratedNames: TArray<string>;
var
fileName: TFileName;
JSONValue, jv: TJSONValue;
begin
fileName := TPath.Combine(ExePath, 'Names.json');
JSONValue := TJSONObject.ParseJSONValue(TFile.ReadAllText(fileName));
try
if JSONValue is TJSONArray then
begin
for jv in TJSONArray(JSONValue) do
begin
Append(Result, (jv as TJSONObject).Get('FirstName').JSONValue.Value);
Append(Result, (jv as TJSONObject).Get('Surname').JSONValue.Value);
end;
end;
finally
JSONValue.Free;
end;
end { GetGeneratedNames };
// XE6 version
uses System.SysUtils, System.JSON, System.IOUtils;
function GetGeneratedNames: TArray<string>;
var
fileName: TFileName;
JSONValue, jv: TJSONValue;
begin
fileName := TPath.Combine(ExePath, 'Names.json');
JSONValue := TJSONObject.ParseJSONValue(TFile.ReadAllText(fileName));
try
if JSONValue is TJSONArray then
begin
for jv in TJSONArray(JSONValue) do
begin
Append(Result, jv.GetValue<string>('FirstName'));
Append(Result, jv.GetValue<string>('Surname'));
end;
end;
finally
JSONValue.Free;
end;
end { GetGeneratedNames };
Комментарии:
1. Ах, элегантность дженериков. И более простое имя модуля System. JSON предполагает, что JSON считается более важным.
2. К счастью, мой Xe4 имеет ту же форму, что и пример XE5. Это сработало!
Ответ №2:
Вы не считываете правильное значение из элементов массива.
Попробуйте что-то вроде этого:
//...
var
JSONArr: TJSONArray;
Item: TJSONValue;
FirstName, Surname, WholeObject: String;
begin
//...
JSONArr := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(TFile.ReadAllText(filename)), 0);
try
for Item in JSONArr do
begin
// Get the first or last names
FirstName := (Item as TJSONObject).GetValue('FirstName').Value;
Surname := (Item as TJSONObject).GetValue('Surname').Value;
// Get the whole string {"FirstName": "Oleg", "Surname": "Buckley"}
WholeObject := Item.ToString;
end;
finally
JSONArr.Free;
end;
// do something with them ...
end;
Объект JSON содержит пары значений, но у него нет самого значения, поэтому вы получаете пустые строки. Если вам нужен весь текст объекта, вы должны использовать метод «toString».
И действительно, SuperObject или XSuperObject проще в использовании и быстрее, если вам приходится работать с большим объемом данных. Второй, похоже, также доступен для iOS / Android, хотя я им не пользовался.
Комментарии:
1. Этот код выглядит красиво и читабельно. Откуда же взялся JSONArr? Он не назначается.
2.
JSONValue
на самом деле должно бытьJSONArr
Ответ №3:
Спасибо tz и VGeorgiev. Вот окончательная форма кода, основанная на вашем:
function GetGeneratedNames: TArray<string>;
var data: TBytes;
JSONValue, jv: TJSONValue;
joName: TJSONObject;
firstName, surname: string;
begin
result := nil;
data := TEncoding.ASCII.GetBytes(TFile.ReadAllText(ExePath 'Names.json'));
JSONValue := TJSONObject.ParseJSONValue(data, 0);
for jv in JSONValue as TJSONArray do begin // Returns TJSONValue
joName := jv as TJSONObject;
firstName := joName.Get('FirstName').JSONValue.Value;
surname := joName.Get('Surname').JSONValue.Value;
Append(Result, surname ', ' firstName);
end{for};
end{ GetGeneratedNames};