Pull to refresh

Comments 19

Вот если бы каждый описывал свою библиотеку так же в Readme — мир стал бы лучше

яй бы смотрел в сторону jsonpath-подобного синтаксиса, чтобы вместо цепоски pull'ов передавать строку типа "key?.nestedkey?.l2_nestedkey?"

разворачивать обратно в голове цепочку pull'ов весьма не удобно

Такой подход реализован в Typed, и в принципе это стандартный способ записи, только вопросики ни кто не пишет, и так понятно, что элемента может не быть.

Но у моей библиотеки другое назначение, я не просто получаю значение, я его ещё и анализирую, было не было, и если было, то какого типа. Редкий сценарий использования, но как то с моим универсальным подходом получилось так. У Typed более практичный подход.

Возьмут динамически типизированные языки, а потом мучаются

Всего 2 вопроса:

1) Чем это решение лучше/хуже symfony serialiser?

2) Есть ли возможность частичной десериализации (например, преобразовать часть json-строки в ассоциативный массив только обнаружения нудного ключа в исходной json-строке?

Объект обёртка создаётся над массивом, конструктор принимает не json-строку, а уже распашеный массив.

Дать json и сказать распарки кусочек - так не получиться.

С symfony serialiser не сравнивал, не в курсе. Но думаю у серилайзера назначение другое, не думаю, что сериалайзер выдаст элемент без приведения типа и выдаст реальный тип элемента, и позволит проверить итоговое значение является подставленным значением по умолчанию или исходное значение такое и было.

Мой пакет предназначен для анализа исходного значения, не только для конвертации в заданный тип.

Мой пакет не является заменой чему либо, у него своя судьба :) своё предназначение, зачем его качают 300 раз в месяц для меня загадка. Из 500 скачиваний в месяц 200 установок это хвосты от установки другого моего пакета, для работы с XML. И тут тоже для меня загадка зачем качать пакет для работы с XML, когда есть более популярные аналоги.

Небольшая поправка

Самое неприятное, что элемента с индексом 0 может и не быть, то есть сначала надо проверить, что он есть, а потом уже читать дальше

Это не совсем так. "Сначала" проверять ничего не надо, эта строка вполне рабочая. Если индекса нет, то мы просто получим значение после ??

элемент "formatted" может внезапно оказаться с типом bool вместо string.

А вот тут уже спорный вопрос, что делать в этом случае. По моим представлениям, в таком случае пришедшие данные скорее не стоит обрабатывать вообще, чем как-то подрихтовывать, только чтобы они пролезли в нужное отверстие, пусть и с пустым значением.

И в любом случае, эта проблема решается тем же (string). Куда интереснее вопрос, что делать, если тип boolean окажется у элемента Address, а не formatted. И в этом смысле мне интереснее была бы библиотека с встроенной валидацией по схеме. Ну то есть такое переизобретение SOAP для JSON. Вот такое я бы действительно назвал типобезопасным. А предложенный вариант скорее типоигнорирующим.

И в этом смысле мне интереснее была бы библиотека с встроенной валидацией по схеме

Ну json schema спасает.

Но вообще я схему исключительно для тестов использую, чтоб матчить ответы на схему и типа с ними всё ок. В клиентском (АПИ там) отдельно валидировать и отдельно маппить -- смысла особо не имеет.

А для клиента маршаллинг/маппинг на ДТО и никаких проблем; Через какой-нибудь JMS, Symfony, Valinor, TypeLang и прочие.

Вполне может быть так, что способ обработки элемента зависит от его типа. У PHP сплошь и рядом надо проверять, что вернулся не false :) Разработчики API тоже могут такие приколы у себя реализовать.

Библиотека была написана для одного сценария использования, потом просто была расширена всем подряд, что бы решать вообще все задачи.

Если не ошибаюсь, в laravel можно так:

Arr::get(
  $response,
  'response.GeoObjectCollection.featureMember.0.GeoObject.metaDataProperty.GeocoderMetaData.Address.formatted',
  'Адрес не найден',
);

Или так:

data_get(
  $response,
  'response.GeoObjectCollection.featureMember.0.GeoObject.metaDataProperty.GeocoderMetaData.Address.formatted',
  'Адрес не найден',
);

Я лично в своей библиотеке unipath.php использую xpath подобный синтаксис для "вытаскивание" данных из сложных структур.
Например вот так: uni("response/response/GeoObjectCollection/featureMember/0/GeoObject/metaDataProperty/GeocoderMetaData/Address/formatted/ifEmpty('Адрес не найден')")

Не думали тоже подобный способ реализовать? Так ведь короче.

Я как раз и хотел уйти от сплошных длинных строчек, мне надо было побить строчку на части.

Писать ifEmpty руками это точно не мой способ, всегда стремлюсь к максимальной автоматизации.

И вы упускаете возможность перебрать все элементы массива, вот этот 0 он же означает, что там может быть 0 .. 100500 элементов, вашим способом придётся строчку клеить, писать лишний foreach , у меня можно перебирая вложенные элементы смотреть на индекс элемента (имя элемента) и от этого применять разные обработки через switch{case:} совсем другой подход к работе с массивами.

$data = (new AdvancedArrayFactory())->makeAdvancedArray($response);
$members = $data
    ->pull("response")
    ->pull("GeoObjectCollection")
    ->pull("featureMember");
foreach($members->arrays() as $index => $dataset)
  {
    foreach($dataset->arrays() as $name => $object)
      switch($name)
        {
          case 'GeoObject':
            /* обработчик для GeoObject */
            if($object->has('metaDataProperty')){
              $metaDataProperty = $object->get('metaDataProperty')->asIs()
                /* что то делаем с $metaDataProperty */
            }
            break;
          case 'SpatialObject':
            /* обработчик для SpatialObject */
            break;
      }
  }

что мы тут сделали ? перебрали все элементы-массивы внутри "featureMember", для каждого "объекта" обработали его свойства соответствующим обработчиком.

Если каких то элементов нет, то ни чего не сломается, код просто проедет мимо, будет работать дальше.

Для такого использования написана моя библиотека, не для того что бы какие то конкретные элементы получить. Получить элемент и поработать с его внутренностями - вот так надо :)

Ясно. Ясно. Я понял Ваш подход. Это хорошо, что Вы придумали свой подход. Больше библиотек - больше шансов найти что-то по душе)

В моём случае вместо 0 можно и $i поставить. Это же строка в двойных кавычках. Можно ещё * поставить, тогда обойдены будут все элементы и результат вернётся списком. Можно и фильтр использовать в [] как в xpath. Есть и функция if() и другие. Но в любом случае Ваш подход тоже хорош: он будет работать быстрее чем у меня. У меня всё таки парсинг выражения происходит перед его исполнением, а это лишние вычисления.

На счёт скорости работы спорно, у меня каждый шаг обработки создаётся новый экземпляр в который передаётся каждый раз новый массив, он прямо копируется, что бы не было возможности "повредить" исходный. В вашем подходе не надо массив копировать, вы просто бегаете по индексам.

Звёздочка (*) это классно, if() - есть, тоже хорошо, у вас получается свой Domain-specific language написан. Если у вас такой богатый функционал, то почему нет статьи ? Пишите, почитаем.

Проблема с вашим DSL только в том, что нет поддержки от IDE, то есть ноль защиты от опечаток и нет статического анализа, но если строчка входит на экран без переносов, то и не беда.

Если у вас такой богатый функционал, то почему нет статьи ?

Ну когда я научусь писать статьи так-же хорошо как и Вы, тогда и напишу) А сейчас меня хватает разве-что на примеры использования на странице проекта на GitHab-е.

Боюсь, сначала надо научиться программировать. Если вы напишете про это статью, у неё будет самый низкий рейтинг за всё время существования этого хаба.

Просто пиздец. И в чем смысл? Вместо квадратных скобок использовать круглые? Для этого нужно было создавать отдельную библиотеку?

Sign up to leave a comment.

Articles