powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Получить подчинённый узел в JSON
21 сообщений из 21, страница 1 из 1
Получить подчинённый узел в JSON
    #39845827
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Напишу сразу, чтобы не было флуда, использую стандартный TJSONObject . Просьба не тратить время на написание примеров, советов для других библиотек. Ну т.е. тот JSONObject использую, что идёт искаропки в Delphi Tokyo.
Да, я знаю, что в других библиотеках может быть проще. А может быть и в стандартной так можно, как я хочу.

Итак. Есть JSON строка, как на картинке для наглядности.
На данный момент, у меня получается говнокод, который сперва получаю TJsonValue, потом TJSONObject для всей строки, т.е. общий JSON-объект, потом всякие проверки. Затем то же самое узла "result", потом всякие проверки. Потом то же самое нужно сделать для узла "ad_parameters" ну и дальше уже цикл по массиву. Могу показать, но страшно )))

А нельзя ли это всё превратить в одну строку типа

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
const 
 sJSON = 'здесь JSON-строка';
var
 JSONParamsVal: TJSONValue;
 JSONArray: TJSONArray;
begin
  JSONParamsVal := TJSONObject.ParseJSONValue(sJSON).Get('result').Get('ad_parameters');

  if JSONParamsVal is TJSONArray then
    JSONArray := TJSONArray(JSONParamsVal);

...
...
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39845856
ёёёёё
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,

сразу же советую переходить на superobject, дальше все одной строкой делается.
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39845916
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
var
  LStr: string;
  LVal: TJSONValue;
  LData: TJSONArray;
begin
  LStr := '{"result":{"ad_parameters": [1, 2, 3]}}';
  LVal := TJSONObject.ParseJSONValue(LStr, True, True);
  try
    LData := LVal.GetValue<TJSONArray>('result.ad_parameters');
  finally
    LVal.Free;
  end;
end;
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39845940
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,
просто супер. Спасиб!
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39845941
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Странно, что я никогда в примерах и справках не видел, что так реально можно.
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39845957
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11Странно, что я никогда в примерах и справках не видел, что так реально можно.
Я тоже. Но я исходил из теории, что так можно. Открыл исходники и посмотрел. Зацепился за имя параметра APath у GetValue. Прочитал в хелпе его формат
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846249
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что не так?
Код: pascal
1.
2.
3.
4.
5.
 LData: TJSONArray;
 JSONPair: TJSONPair;
begin

  for JSONPair in LData do



Incompatible types: 'TJSONPair' and 'TJSONValue'

Как правильно сделать цикл по TJSONArray?
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846255
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Нужно объявить JSONPair как TJSONValue
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846327
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11,
Дерево и его узлы - это в XML. В JSON (JavaScript Object Notation) - объекты и их свойства, массивы и их элементы. В том числе, само собой - вложенные объекты. Мне кажется, если это понимать, то какие-то вопросы решаются. Объект состояит из пар - имя-значение.
JSONОбъект - неупорядоченный набор пар ключ/значение. Объект начинается с {открывающей фигурной скобки и заканчивается }закрывающей фигурной скобкой.
https://www.json.org/json-ru.html
Массив - из элементов.
JSONМассив - упорядоченная коллекция значений. Массив начинается с [открывающей квадратной скобки и заканчивается ]закрывающей квадратной скобкой.
Чем является этот элемент массива или значение пары в объекте - объектом, массивом или чем-то еще - это уже другое дело.
Исходя из этого, получается и ответ на ваш вопрос.
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846329
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
s62,
я написал, что массив состоит из элементов, для вопроса "Как правильно сделать цикл по TJSONArray? " важней наверное, что каждый элемент это значение (а не пара), как написано в процитированном мной определении с сайта JSON.
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846334
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
значения
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846398
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А почему Delphi не разрешает проверить тип?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
Var
 LVal, JSONPair: TJSONValue;
 LData, lData2: TJSONArray;
begin

  if JSONPair is TJSONPair then
    result := TJSONPair(JSONPair).JsonString.Value;



Incompatible types: 'TJSONValue' and 'TJSONPair'
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846464
Cobalt747
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11А почему Delphi не разрешает проверить тип?
Incompatible types: 'TJSONValue' and 'TJSONPair'Эти классы не являются потомками один другого. и значит заведомо не могут быть совместимы.
можно TObject проверять на любой класс, ибо он предок для всех.
аналогично как с
Код: pascal
1.
2.
3.
4.
var
 q: TList;
begin
  if q is TStringList then


объявляй JSONPair как предок обоих классов, т.е. TJSONAncestor
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846571
s62
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
X11значения

Правильно, как я и написал, каждый элемент массива является значением, а не парой имя:значение. Поэтому и нужно
Код: pascal
1.
2.
3.
4.
5.
 LData: TJSONArray;
 JSONValue: TJSONValue;
begin

  for JSONValue in LData do


а не использовать TJSONPair, как было сначала у вас. А вот это значение уже в свою очередь может быть числом, строкой, true, false, null, объектом или массивом. В вашем случае по этой схеме мне не совсем понятно, то ли объекты, то ли массивы.
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846859
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_, а можно как-то добраться таким описанным тобою способом до элемента "p" и получить его значение?
Или только полным перебором всех элементов?
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846880
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Можно ли этого монстра упростить/оптимизировать или всё правильно?

Задача: получить значение элемента "vl", но только если значение элемента "p" соответствует какому-то определённому значению, в данном случае "area". У других элементов этого списка (ad_parameters) - другие значения. Грубо говоря, нужно найти город.


Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
Function GetADParamFromRendered(const sJSON, path, param_name: string): string;
Var
 LVal, JSONPair: TJSONValue;
 ad_param: TJSONObject;
 LData: TJSONArray;
 i: integer;
begin

  LVal := TJSONObject.ParseJSONValue(sJSON);
  try
    LData := LVal.GetValue<TJSONArray>(path);// 'result.ad_parameters'

    if LData is TJSONArray then
    begin
      for JSONPair in LData do
      begin
        if JSONPair is TJSONObject then
        begin

          ad_param := JSONPair as TJSONObject;// pl, vl, p или v

          for i := 0 to pred(ad_param.Count) do
          begin
            // получаем значение пары "vl"
            if ad_param.Pairs[i].JsonString.Value = 'vl' then
              result := ad_param.Pairs[i].JsonValue.Value;

            // если пара с именем "p" имеет искомое значение param_name, то и значение элемента "vl" правильное
            if (ad_param.Pairs[i].JsonString.Value = 'p') and
               (ad_param.Pairs[i].JsonValue.Value = param_name) // нашли нужный элемент category или region
            then
              exit;// нашли, в result будет нужное значение

          end;//for 
        end;// if 
      end;// for
    end;// if

  finally
    LVal.Free;
  end;

end;
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39846885
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
количество элементов в массиве ad_parameters может быть разное и неизвестно заранее, в каком индексе живёт тот или иной элемент.
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39847068
Василий 2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
проверки не заворачивать во вложенные блоки, а делать Exit после негативного результата.
А зачем перебор параметров, если они у тебя четко определенные?
Код: pascal
1.
if JSONPair.Get('p') = param_value then Exit(JSONPair.Get('v1'))



Ну а в целом нужно что-то вроде xpath, наверняка можно добавить функцию с поиском через хелперы, чтобы писать так
Код: pascal
1.
Get('result.ad_parameters').Find('[].p='+param_value).Get('v1')
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39847296
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Василий 2А зачем перебор параметров, если они у тебя четко определенные?

спасибо
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39847381
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Но у JSONPair отсутствует метод Get
...
Рейтинг: 0 / 0
Получить подчинённый узел в JSON
    #39847389
Фотография X11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В общем, сократил до
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
Function GetADParamFromRendered(const sJSON, path, p_param_name: string): string;
Var
 LVal, JSONPair: TJSONValue;
 ad_param: TJSONObject;
 LData: TJSONArray;
 i: integer;
 s, v: string;
begin

  LVal := TJSONObject.ParseJSONValue(sJSON);
  try
    LData := LVal.GetValue<TJSONArray>(path);// 'result.ad_parameters'

    if LData is TJSONArray then
    begin
      for JSONPair in LData do
      begin
        if JSONPair is TJSONObject then
        begin
          ad_param := JSONPair as TJSONObject;

          if JSONPair.GetValue<TJSONString>('p').Value = p_param_name then
            exit(JSONPair.GetValue<TJSONString>('vl').Value);

        end;// if
      end;// for
    end;// if

  finally
    LVal.Free;
  end;

end;



ещё раз спасибо
...
Рейтинг: 0 / 0
21 сообщений из 21, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Получить подчинённый узел в JSON
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]