Определите тип jsonable, используя mypy/PEP-526

Значения, которые можно преобразовать в строку JSON с помощью json.dumps: - Скаляры: числа и строки - Контейнеры: сопоставление и итерация

Union[str, int, float, Mapping, Iterable]

У вас есть лучшее предложение?


person Terris    schedule 11.07.2018    source источник
comment
К сожалению, я забыл логическое значение -- mypy нужен скаляр   -  person Terris    schedule 14.07.2018
comment
кортеж является итерируемым, но не поддерживает jsonify   -  person Sławomir Lenart    schedule 13.05.2020


Ответы (2)


К сожалению, правильно набирать большие двоичные объекты JSON неудобно для типов PEP 484. Отчасти это связано с тем, что в mypy (в настоящее время) отсутствуют рекурсивные типы: это означает, что лучшее, что мы можем сделать, — это использовать типы, подобные созданному вами.

(Однако мы можем внести некоторые уточнения в ваш тип. В частности, json.Dumps(...) на самом деле не принимает произвольные итерации. Генератор, например, является подтипом Iterable, но json.dumps(...) откажется сериализовать генераторы. как Sequence вместо этого.)

Другая причина заключается в том, что даже если бы у нас были рекурсивные типы, функции, возвращающие объединения, часто заканчиваются тем, что вызывают много неудобств для вызывающей стороны, которой часто приходится прибегать к утверждению или приведению типов, чтобы получить тип, который они ожидают. (Аналогичным образом наличие функции, принимающей объединения в качестве параметра, может аналогичным образом усложнить реализацию, хотя во многих случаях сложности — это то, что вам все равно пришлось бы делать, а не код, который вы написали только для проверки типа).

По этой причине многие люди просто используют Dict[str, Any] для представления словаря JSON. Очевидно, что это менее точно, чем ваша подпись, но простые типы, подобные этим, на практике часто оказываются более эргономичными.

В качестве альтернативы, если вы хотите перейти к более безопасному типу, вы можете попробовать использовать TypedDicts вместо этого. По сути, вы создаете тип, явно указывающий, как должен выглядеть конкретный большой двоичный объект JSON, и используете его вместо этого. Это требует дополнительной работы, но может повысить безопасность типов.

Тем не менее, этот маршрут, как правило, является лучшим, если вы можете ожидать некоторую структуру в больших двоичных объектах JSON, с которыми вы манипулируете. (Например, если вы вызываете какой-либо API и знаете, что он вернет некоторый JSON в определенном формате). Если ваша программа должна манипулировать действительно произвольными блобами JSON, боюсь, вам придется жить с неточными/динамическими типами в той или иной форме.


tl;dr:

  • Ваш тип работает с небольшими изменениями (например, используйте Sequence вместо Iterable)
  • Поскольку произвольные BLOB-объекты JSON трудно вводить безопасным для типов способом, некоторые люди используют более простые типы, такие как Dict[str, Any], признают, что JSON по своей природе динамичен, и возвращаются к использованию проверок во время выполнения.
  • Если мы можем ожидать, что наши большие двоичные объекты JSON будут структурированы определенным образом, мы можем представить их с помощью TypedDicts (конечно, в сочетании с другими типами).
person Michael0x2a    schedule 11.07.2018