Django — custom type json encoder


Содержание

Модуль json

JSON (JavaScript Object Notation) — простой формат обмена данными, основанный на подмножестве синтаксиса JavaScript. Модуль json позволяет кодировать и декодировать данные в удобном формате.

Кодирование основных объектов Python:

Декодирование (парсинг) JSON:

Основы

json.dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) — сериализует obj как форматированный JSON поток в fp.

Если skipkeys = True, то ключи словаря не базового типа (str, unicode, int, long, float, bool, None) будут проигнорированы, вместо того, чтобы вызывать исключение TypeError.

Если ensure_ascii = True, все не-ASCII символы в выводе будут экранированы последовательностями \uXXXX, и результатом будет строка, содержащая только ASCII символы. Если ensure_ascii = False, строки запишутся как есть.

Если check_circular = False, то проверка циклических ссылок будет пропущена, а такие ссылки будут вызывать OverflowError.

Если allow_nan = False, при попытке сериализовать значение с запятой, выходящее за допустимые пределы, будет вызываться ValueError (nan, inf, -inf) в строгом соответствии со спецификацией JSON, вместо того, чтобы использовать эквиваленты из JavaScript (NaN, Infinity, -Infinity).

Если indent является неотрицательным числом, то массивы и объекты в JSON будут выводиться с этим уровнем отступа. Если уровень отступа 0, отрицательный или «», то вместо этого будут просто использоваться новые строки. Значение по умолчанию None отражает наиболее компактное представление. Если indent — строка, то она и будет использоваться в качестве отступа.

Если sort_keys = True, то ключи выводимого словаря будут отсортированы.

json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) — сериализует obj в строку JSON-формата.

Аргументы имеют то же значение, что и для dump().

json.load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) — десериализует JSON из fp.

object_hook — опциональная функция, которая применяется к результату декодирования объекта (dict). Использоваться будет значение, возвращаемое этой функцией, а не полученный словарь.

object_pairs_hook — опциональная функция, которая применяется к результату декодирования объекта с определённой последовательностью пар ключ/значение. Будет использован результат, возвращаемый функцией, вместо исходного словаря. Если задан так же object_hook, то приоритет отдаётся object_pairs_hook.

parse_float, если определён, будет вызван для каждого значения JSON с плавающей точкой. По умолчанию, это эквивалентно float(num_str).

parse_int, если определён, будет вызван для строки JSON с числовым значением. По умолчанию эквивалентно int(num_str).

parse_constant, если определён, будет вызван для следующих строк: «-Infinity», «Infinity», «NaN». Может быть использовано для возбуждения исключений при обнаружении ошибочных чисел JSON.

Если не удастся десериализовать JSON, будет возбуждено исключение ValueError.

json.loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) — десериализует s (экземпляр str, содержащий документ JSON) в объект Python.

Остальные аргументы аналогичны аргументам в load().

Кодировщики и декодировщики

Класс json.JSONDecoder(object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None) — простой декодер JSON.

Выполняет следующие преобразования при декодировании:

JSON Python
object dict
array list
string str
number (int) int
number (real) float
true True
false False
null None

Он также понимает NaN, Infinity, и -Infinity как соответствующие значения float, которые находятся за пределами спецификации JSON.

Класс json.JSONEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)

Расширяемый кодировщик JSON для структур данных Python. Поддерживает следующие объекты и типы данных по умолчанию:

django-numpy-json-encoder 0.1.3

pip install django-numpy-json-encoder Copy PIP instructions

Last released: May 31, 2020

Django JSON encoder with numpy support.

Statistics

View statistics for this project via Libraries.io, or by using Google BigQuery

License: MIT License (MIT)

Requires: Python

Maintainers

Classifiers

  • Development Status
    • 3 — Alpha
  • Framework
    • Django
    • Django :: 2.0
  • Intended Audience
    • Developers

  • License
    • OSI Approved :: MIT License
  • Natural Language
    • English
  • Operating System
    • OS Independent
  • Programming Language
    • Python :: 3 :: Only
    • Python :: 3.6
    • Python :: Implementation :: CPython
    • Python :: Implementation :: PyPy

Project description

Introduction

Subclass of standard Django JSON encoder [1] that can encode some numpy types (integers, floats and arrays).

Installation

  • Supported Python versions are: 3.6 and 3.7-dev .
  • Supported Django versions are: 2.0

Usage

License

The MIT License (MIT)

Project details

Statistics

View statistics for this project via Libraries.io, or by using Google BigQuery

License: MIT License (MIT)

Requires: Python

Maintainers

Classifiers

  • Development Status
    • 3 — Alpha
  • Framework
    • Django
    • Django :: 2.0
  • Intended Audience
    • Developers
  • License
    • OSI Approved :: MIT License
  • Natural Language
    • English
  • Operating System
    • OS Independent
  • Programming Language
    • Python :: 3 :: Only
    • Python :: 3.6
    • Python :: Implementation :: CPython
    • Python :: Implementation :: PyPy

Release history Release notifications

Download files

Download the file for your platform. If you’re not sure which to choose, learn more about installing packages.

JSON в Python


Сразу после появления, JSON быстро стал де факто стандартом обмена информации. Вероятно вы здесь из-за того, что вы хотите переместить данные из одного места в другое. Возможно вы получаете данные через API, или храните их в документной базе данных. Так или иначе, вы заинтересовались JSON, и вам нужно пользоваться им через Python.

Содержание

К счастью, это достаточно тривиальная задача, и как и с большинством тривиальных задач, Python делает все до омерзения простым.

Итак, используем ли мы JSON для хранения и обмена данными? Именно так. Это не более, чем стандартизированный формат, который используется сообществом для передачи данных. Помните, что JSON не является единственным доступным форматом для такой работы, XML и YAML наверное, единственные альтернативные способы, которые стоит упомянуть.

Подробнее про JSON

Не удивительно, что JavaScript Object Notation был вдохновен подмножеством языка программирования JavaScript, связанным с синтаксисом объектного литерала. У них есть отличный сайт, в котором все прекрасно объясняется. Не переживайте: JSON уже давно стал агностиком языка и существует как отдельный стандарт, по этому мы можем убрать JavaScript из этой дискуссии.

В конечном счете, большая часть сообщества приняла JSON благодаря его простоте как для людей, так и для машин.
Смотрите, это JSON!

Структура JSON

Готовьтесь. Я собираюсь показать реальный пример JSON— такой же, какой вы встретите в реальной жизни. Это нормально, подразумевается что JSON является читаемым для любого, кто пользовался С-языками, а Python – это С-язык, так что мы говорим о вас!

Как видите, JSON поддерживает примитивные типы, такие как строки python и числа, а также вложенные списки и объекты.

Погодите, это выглядит как словарь Python, верно? На данный момент это достаточно универсальная нотация объектов, и не думаю что UON может так же легко отскакивать от зубов. Кстати, предлагайте альтернативы в комментариях!

НУ что же, вы пережили первый контакт с диким JSON. Теперь вам нужно научиться приручать его!

Python поддерживает JSON

Python содержит встроенный модуль под названием json для кодирования и декодирования данных JSON.

Просто импортируйте модуль в начале вашего файла:

Небольшой словарь

Как правило, процесс кодирования JSON называется сериализация. Этот термин обозначает трансформацию данных в серию байтов (следовательно, серийных) для хранения или передачи по сети. Также вы, возможно, уже слышали о термине «маршалинг», но это уже совсем другая область.

Естественно, десериализация — является противоположным процессом декодирования данных, которые хранятся или направлены в стандарт JSON.

Звучит как много технических терминов. Определенно. Но в реальности, все, о чем мы сейчас говорим — это чтение и написание. Представьте это следующим образом: кодирование это запись данных на диск, в то время как декодирование — это чтение данных в памяти.

Сериализация JSON

Что происходит после того, как компьютер обрабатывает большие объемы информации? Ему нужно принять дамп данных. Соответственно, модуль json предоставляет метод dump() для записи данных в файлы. Также есть метод dumps() для записей в строку Python.

Простые объекты Python переводятся в JSON согласно с весьма интуитивной конверсией.

Python JSON
dict object
list, tuple array
str string
int, long, float number
True true
False false
None null

Пример сериализации JSON Python

Представьте, что вы работаете с объектом Python в памяти, который выглядит следующим образом:

Сохранить эту информацию на диск — критично, так что ваша задача — записать на файл.

Используя контекстный менеджер Python, вы можете создать файл под названием data_file.json и открыть его в режиме write (файлы JSON имеют расширение .json).

Обратите внимание на то, что dump() принимает два позиционных аргумента: (1) объект данных, который сериализуется и (2), файловый объект, в который будут вписаны байты.

Или, если вы склонны продолжать использовать эти сериалзированные данные JSON в вашей программе, вы можете работать как со строкой.

Обратите внимание, что файловый объект является пустым, так как вы на самом деле не выполняете запись на диск. Кроме того, dumps() аналогичен dump().

Ура! У вас получился малыш JSON и вы можете выпустить его в реальный мир, чтобы он вырос большим и сильным.

Несколько полезных аргументов

Помните, что JSON создан таким образом, чтобы быть читаемым для людей. Но читаемого синтаксиса недостаточно, если все слеплено вместе. Кроме этого, ваш стиль программирования скорее всего отличается от моего, и вам будет проще читать код, если он отформатирован по вашему вкусу.

Обратите внимание: Методы dump() и dumps() пользуются одними и теми же аргументами ключевых слов.

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

Еще один вариант форматирования — это аргумент separators. По умолчанию, это двойной кортеж строк разделителя («, «, «: «), но обычно в качестве альтернативы для компактного JSON является («,», «:»). Взгляните на пример JSON еще раз, чтобы понять, где в игру вступают разделители.

Есть и другие аргументы, такие как sort_keys, но я не имею понятия, что он делает. Вы можете найти полный список в документации, если вам интересно.

Десериализация JSON

Отлично, похоже вам удалось поймать экземпляр дикого JSON! Теперь нам нужно предать ему форму. В модуле json вы найдете load() и loads() для превращения кодированных данных JSON в объекты Python.

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

JSON
Python
object dict
array list
string str
number (int) int
number (real) float
true True
false False
null None

Технически, эта конверсия не является идеальной инверсией таблицы сериализации. По сути, это значит что если вы кодируете объект сейчас, а затем декодируете его в будущем, вы можете не получить тот же объект назад. Я представляю это как своего рода телепортацию: мои молекулы распадаются в точке А и собираются в точке Б. Буду ли я тем же самым человеком?

В реальности, это как попросить одного друга перевести что-нибудь на японский, а потом попросить другого друга перевести это обратно на русский. В любом случае, самым простым примером будет кодировать кортеж и получить назад список после декодирования, вот так:

Django newforms ExtJS JSON Encoder

This is a subclass of Django’s built-in JSONEncoder that adds the ability to output form and field objects as ExtJS-compatible config objects.

Simple example: from django.utils import simplejson json = < 'data': [], 'success': True, 'metaData': < 'fields': SFY09RDOForm(), 'root': 'data', 'successProperty': 'success' >, > return HttpResponse(simplejson.dumps(json, cls=ExtJSONEncoder))

Where SFY09RDOForm is a subclass of django.forms.Form.

6/20/2008: Updated to pass on the help_text parameter (useful in combination with this overr >


More like this

Comments

that is I need, thanks

I’m new to Django. Can you provide a simple example on how to integrate this into a ModelForm?

Hello, thanks for the code, can you provide a working example? Thank you!

Please login first before commenting.

Written by various people. Hosted by Heroku, powered by Django

Renderers

Before a TemplateResponse instance can be returned to the client, it must be rendered. The rendering process takes the intermediate representation of template and context, and turns it into the final byte stream that can be served to the client.

REST framework includes a number of built in Renderer classes, that allow you to return responses with various media types. There is also support for defining your own custom renderers, which gives you the flexibility to design your own media types.

How the renderer is determined

The set of valid renderers for a view is always defined as a list of classes. When a view is entered REST framework will perform content negotiation on the incoming request, and determine the most appropriate renderer to satisfy the request.

The basic process of content negotiation involves examining the request’s Accept header, to determine which media types it expects in the response. Optionally, format suffixes on the URL may be used to explicitly request a particular representation. For example the URL http://example.com/api/users_count.json might be an endpoint that always returns JSON data.

For more information see the documentation on content negotiation.

Setting the renderers

The default set of renderers may be set globally, using the DEFAULT_RENDERER_CLASSES setting. For example, the following settings would use JSON as the main media type and also include the self describing API.

You can also set the renderers used for an individual view, or viewset, using the APIView class-based views.

Or, if you’re using the @api_view decorator with function based views.

Ordering of renderer classes

It’s important when specifying the renderer classes for your API to think about what priority you want to assign to each media type. If a client underspecifies the representations it can accept, such as sending an Accept: */* header, or not including an Accept header at all, then REST framework will select the first renderer in the list to use for the response.

For example if your API serves JSON responses and the HTML browsable API, you might want to make JSONRenderer your default renderer, in order to send JSON responses to clients that do not specify an Accept header.

If your API includes views that can serve both regular webpages and API responses depending on the request, then you might consider making TemplateHTMLRenderer your default renderer, in order to play nicely with older browsers that send broken accept headers.

API Reference

JSONRenderer

Renders the request data into JSON , using utf-8 encoding.

Note that the default style is to include unicode characters, and render the response using a compact style with no unnecessary whitespace:

The client may additionally include an ‘indent’ media type parameter, in which case the returned JSON will be indented. For example Accept: application/json; indent=4 .

The default JSON encoding style can be altered using the UNICODE_JSON and COMPACT_JSON settings keys.

.media_type: application/json

.format: ‘json’

.charset: None

TemplateHTMLRenderer

Renders data to HTML, using Django’s standard template rendering. Unlike other renderers, the data passed to the Response does not need to be serialized. Also, unlike other renderers, you may want to include a template_name argument when creating the Response .

The TemplateHTMLRenderer will create a RequestContext , using the response.data as the context dict, and determine a template name to use to render the context.

The template name is determined by (in order of preference):

  1. An explicit template_name argument passed to the response.
  2. An explicit .template_name attribute set on this class.
  3. The return result of calling view.get_template_names() .

An example of a view that uses TemplateHTMLRenderer :

You can use TemplateHTMLRenderer either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint.

If you’re building websites that use TemplateHTMLRenderer along with other renderer classes, you should consider listing TemplateHTMLRenderer as the first class in the renderer_classes list, so that it will be prioritised first even for browsers that send poorly formed ACCEPT: headers.

See the HTML & Forms Topic Page for further examples of TemplateHTMLRenderer usage.

.media_type: text/html

.format: ‘html’

.charset: utf-8

See also: StaticHTMLRenderer

StaticHTMLRenderer

A simple renderer that simply returns pre-rendered HTML. Unlike other renderers, the data passed to the response object should be a string representing the content to be returned.

An example of a view that uses StaticHTMLRenderer :

You can use StaticHTMLRenderer either to return regular HTML pages using REST framework, or to return both HTML and API responses from a single endpoint.


.media_type: text/html

.format: ‘html’

.charset: utf-8

See also: TemplateHTMLRenderer

BrowsableAPIRenderer

Renders data into HTML for the Browsable API:

This renderer will determine which other renderer would have been given highest priority, and use that to display an API style response within the HTML page.

.media_type: text/html

.format: ‘api’

.charset: utf-8

.template: ‘rest_framework/api.html’

Customizing BrowsableAPIRenderer

By default the response content will be rendered with the highest priority renderer apart from BrowsableAPIRenderer . If you need to customize this behavior, for example to use HTML as the default return format, but use JSON in the browsable API, you can do so by overriding the get_default_renderer() method. For example:

AdminRenderer

Renders data into HTML for an admin-like display:

This renderer is suitable for CRUD-style web APIs that should also present a user-friendly interface for managing the data.

Note that views that have nested or list serializers for their input won’t work well with the AdminRenderer , as the HTML forms are unable to properly support them.

Note: The AdminRenderer is only able to include links to detail pages when a properly configured URL_FIELD_NAME ( url by default) attribute is present in the data. For HyperlinkedModelSerializer this will be the case, but for ModelSerializer or plain Serializer classes you’ll need to make sure to include the field explicitly. For example here we use models get_absolute_url method:

.media_type: text/html

.format: ‘admin’

.charset: utf-8

.template: ‘rest_framework/admin.html’

HTMLFormRenderer

Renders data returned by a serializer into an HTML form. The output of this renderer does not include the enclosing

For more information see the HTML & Forms documentation.

.media_type: text/html

.format: ‘form’

.charset: utf-8

.template: ‘rest_framework/horizontal/form.html’

MultiPartRenderer

This renderer is used for rendering HTML multipart form data. It is not suitable as a response renderer, but is instead used for creating test requests, using REST framework’s test client and test request factory.

.media_type: multipart/form-data; boundary=BoUnDaRyStRiNg

.format: ‘multipart’

.charset: utf-8

Custom renderers

To implement a custom renderer, you should override BaseRenderer , set the .media_type and .format properties, and implement the .render(self, data, media_type=None, renderer_context=None) method.

The method should return a bytestring, which will be used as the body of the HTTP response.

The arguments passed to the .render() method are:

The request data, as set by the Response() instantiation.

media_type=None

Optional. If provided, this is the accepted media type, as determined by the content negotiation stage.

Depending on the client’s Accept: header, this may be more specific than the renderer’s media_type attribute, and may include media type parameters. For example «application/json; nested=true» .

renderer_context=None

Optional. If provided, this is a dictionary of contextual information provided by the view.

By default this will include the following keys: view , request , response , args , kwargs .

Example

The following is an example plaintext renderer that will return a response with the data parameter as the content of the response.

Setting the character set


By default renderer classes are assumed to be using the UTF-8 encoding. To use a different encoding, set the charset attribute on the renderer.

Note that if a renderer class returns a unicode string, then the response content will be coerced into a bytestring by the Response class, with the charset attribute set on the renderer used to determine the encoding.

If the renderer returns a bytestring representing raw binary content, you should set a charset value of None , which will ensure the Content-Type header of the response will not have a charset value set.

In some cases you may also want to set the render_style attribute to ‘binary’ . Doing so will also ensure that the browsable API will not attempt to display the binary content as a string.

Advanced renderer usage

You can do some pretty flexible things using REST framework’s renderers. Some examples.

  • Provide either flat or nested representations from the same endpoint, depending on the requested media type.
  • Serve both regular HTML webpages, and JSON based API responses from the same endpoints.
  • Specify multiple types of HTML representation for API clients to use.
  • Underspecify a renderer’s media type, such as using media_type = ‘image/*’ , and use the Accept header to vary the encoding of the response.

Varying behaviour by media type

In some cases you might want your view to use different serialization styles depending on the accepted media type. If you need to do this you can access request.accepted_renderer to determine the negotiated renderer that will be used for the response.

Underspecifying the media type

In some cases you might want a renderer to serve a range of media types. In this case you can underspecify the media types it should respond to, by using a media_type value such as image/* , or */* .

If you underspecify the renderer’s media type, you should make sure to specify the media type explicitly when you return the response, using the content_type attribute. For example:

Designing your media types

For the purposes of many Web APIs, simple JSON responses with hyperlinked relations may be sufficient. If you want to fully embrace RESTful design and HATEOAS you’ll need to consider the design and usage of your media types in more detail.

In the words of Roy Fielding, «A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types.».

For good examples of custom media types, see GitHub’s use of a custom application/vnd.github+json media type, and Mike Amundsen’s IANA approved application/vnd.collection+json JSON-based hypermedia.

HTML error views

Typically a renderer will behave the same regardless of if it’s dealing with a regular response, or with a response caused by an exception being raised, such as an Http404 or PermissionDenied exception, or a subclass of APIException .

If you’re using either the TemplateHTMLRenderer or the StaticHTMLRenderer and an exception is raised, the behavior is slightly different, and mirrors Django’s default handling of error views.

Exceptions raised and handled by an HTML renderer will attempt to render using one of the following methods, by order of precedence.

  • Load and render a template named .html .
  • Load and render a template named api_exception.html .
  • Render the HTTP status code and text, for example «404 Not Found».

Templates will render with a RequestContext which includes the status_code and details keys.

Note: If DEBUG=True , Django’s standard traceback error page will be displayed instead of rendering the HTTP status code and text.

Third party packages

The following third party packages are also available.

REST framework YAML provides YAML parsing and rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.

Installation & configuration

Install using pip.

Modify your REST framework settings.

REST Framework XML provides a simple informal XML format. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.

Installation & configuration

Install using pip.

Modify your REST framework settings.

JSONP

REST framework JSONP provides JSONP rendering support. It was previously included directly in the REST framework package, and is now instead supported as a third-party package.

Warning: If you require cross-domain AJAX requests, you should generally be using the more modern approach of CORS as an alternative to JSONP . See the CORS documentation for more details.

The jsonp approach is essentially a browser hack, and is only appropriate for globally readable API endpoints, where GET requests are unauthenticated and do not require any user permissions.

Installation & configuration

Install using pip.

Modify your REST framework settings.

MessagePack

MessagePack is a fast, efficient binary serialization format. Juan Riaza maintains the djangorestframework-msgpack package which provides MessagePack renderer and parser support for REST framework.

XLSX (Binary Spreadsheet Endpoints)

XLSX is the world’s most popular binary spreadsheet format. Tim Allen of The Wharton School maintains drf-renderer-xlsx, which renders an endpoint as an XLSX spreadsheet using OpenPyXL, and allows the client to download it. Spreadsheets can be styled on a per-view basis.

Installation & configuration

Install using pip.


Modify your REST framework settings.

To avoid having a file streamed without a filename (which the browser will often default to the filename «download», with no extension), we need to use a mixin to override the Content-Disposition header. If no filename is provided, it will default to export.xlsx . For example:

Comma-separated values are a plain-text tabular data format, that can be easily imported into spreadsheet applications. Mjumbe Poe maintains the djangorestframework-csv package which provides CSV renderer support for REST framework.

UltraJSON

UltraJSON is an optimized C JSON encoder which can give significantly faster JSON rendering. Jacob Haslehurst maintains the drf-ujson-renderer package which implements JSON rendering using the UJSON package.

CamelCase JSON

djangorestframework-camel-case provides camel case JSON renderers and parsers for REST framework. This allows serializers to use Python-style underscored field names, but be exposed in the API as Javascript-style camel case field names. It is maintained by Vitaly Babiy.

Pandas (CSV, Excel, PNG)

Django REST Pandas provides a serializer and renderers that support additional data processing and output via the Pandas DataFrame API. Django REST Pandas includes renderers for Pandas-style CSV files, Excel workbooks (both .xls and .xlsx ), and a number of other formats. It is maintained by S. Andrew Sheppard as part of the wq Project.

LaTeX

Rest Framework Latex provides a renderer that outputs PDFs using Laulatex. It is maintained by Pebble (S/F Software).

Django, JSON и формы

Очень интересные результаты выдает Google при поиске по словам django json forms . Большая часть ссылок ведет на Stack Overflow, но там всё одно и то же. Как правило, всё сводится к тому, чтобы: 1) сменить стек технологий; 2) разобрать request.POST как словарь (это не работает); 3) передать данные каким-то другим способом.

А вот рабочее решение, проверенное в Django 1.4.22 (из-за некоторых особенностей мне сейчас приходится пользоваться именно таким старьем).

Насчет JsonResponse тоже надо пару слов сказать. В старых версиях такого класса нет, но он отлично портируется из новых. Вот код:

JSON для любителей скобочек

Продолжая тему «Ненормальное программирование и JSON» меня посетила еще одна мысль об еще одном представлении JSON данных.

В своей прошлой статье «Усложнённый упрощённый JSON» я уже рассказал о формате NSNJSON, который позволяет представить любые JSON данные с помощью всего 4 JSON типов: number, string, array, object.

На этот раз я расскажу о способе представления любых JSON данных с помощью всего 3 типов: number, string, array.

Содержание

История

После публикации статьи о формате NSNJSON я начал работать над драйверами для этого формата. Практически сразу же у меня возникла идея предоставления пользователям драйвера возможность использовать свои правила для кодирования/декодирования JSON.

В ходе работы над этой идеей я пытался придумать интересный пример пользовательских правил… И вот однажды, меня и посетила это безумная мысль под кодовым названием «Brackets».

Я подумал, что было бы интересно посмотреть на JSON данные, которые представлены с помощью строк, чисел и скобочек!

Проект «Brackets»

Для начала введем таблицу констант для JSON типов.

JSON тип number string true false array object
Маркер 1 2 3 3 4 5

Для типа null всё очень просто. Просто отображаем его на пустой массив.

Определим представление для значения value типа string:

Определим представление для значения value типа string:

Определим представление для значения value типа boolean (true, false):

Остались массивы и объекты. Начну с массивов. Для массивов можно определить представление так:

С объектами чуть сложнее, ведь необходимо сохранять информацию о полях объекта.
Сначала определим представление для поля объекта.
Пусть поле объекта имеет имя name и значение value. Тогда представление определим так:

Теперь можно определить представление для всего объекта целиком:

Определив такие представления очень легко определить и алгоритм восстановления JSON.
— В случае, если мы сталкиваемся с пустым массивом, — значит встретили представление значения типа null.
— Иначе, берем первый элемент массива и ищем по нему соотвествующее имя JSON типа. Далее, драйвер в соответствии с полученным типом вызовет нужную функцию декодирования.

Реализация

Я покажу реализацию такого представления с помощью NSNJSON Node.js драйвера.

Драйвер опубликован на npmjs.com, поэтому для установки драйвера достаточно выполнить простую команду:

Перед тем, как я начну рассказывать о реализации, хочу отметить, что драйвер использует Maybe из пакета data.maybe.

Для начала определим два файла констант.

Константы маркеров (custom.format.json):

Константы имен JSON типов (nsnjson.types.json):

Теперь необходимо задать собственные правила представления/восстановления JSON.

Ну а теперь посмотрим как этим пользоваться.

Примерчики

По традиции, привожу примерчики применения данного алгоритма представления JSON данных.

Using JSON with Custom Types

Demonstrates approaches for encoding and decoding different kinds of JSON in Swift.

Overview

JSON data you send or receive from other apps, services, and files can come in many different shapes and structures. Use the techniques described in this sample to handle the differences between external JSON data and your app’s model types.


This sample defines a simple data type, Grocery Product , and demonstrates how to construct instances of that type from several different JSON formats.

Read Data from Arrays

Use Swift’s expressive type system to avoid manually looping over collections of identically structured objects. This playground uses array types as values to see how to work with JSON that’s structured like this:

Change Key Names

Learn how to map data from JSON keys into properties on your custom types, regardless of their names. For example, this playground shows how to map the «product _name» key in the JSON below to the name property on Grocery Product :

Custom mappings let you to apply the Swift API Design Guidelines to the names of properties in your Swift model, even if the names of the JSON keys are different.

Access Nested Data

Learn how to ignore structure and data in JSON that you don’t need in your code. This playground uses an intermediate type to see how to extract grocery products from JSON that looks like this to skip over unwanted data and structure:

Merge Data at Different Depths

Combine or separate data from different depths of a JSON structure by writing custom implementations of protocol requirements from Encodable and Decodable . This playground shows how to construct a Grocery Product instance from JSON that looks like this:

Как вы сериализуете экземпляр модели в Django?

Существует много документации о том, как сериализовать модель QuerySet, но как вы просто сериализуете в JSON поля экземпляра модели?

Вы можете легко использовать список для переноса требуемого объекта и что все, что сериализаторы django должны правильно сериализовать, например:

Если вы имеете дело со списком экземпляров модели, лучше всего использовать serializers.serialize() , он идеально подойдет вам.

Однако вы столкнулись с проблемой с попыткой сериализации одного объекта, а не list объектов. Таким образом, чтобы избавиться от разных хаков, просто используйте Django model_to_dict (если я не ошибаюсь, serializers.serialize() тоже полагается на него):

Теперь вам просто нужен один прямой вызов json.dumps для сериализации его в json:

Чтобы избежать обертки массива, удалите его перед возвратом ответа:

Я нашел этот интересный пост по этому вопросу:

Он использует django.forms.models.model_to_dict, который выглядит как идеальный инструмент для работы.

Похоже на то, о чем вы спрашиваете, включает сериализацию структуры данных экземпляра модели Django для обеспечения совместимости. Другие плакаты верны: если вы хотите, чтобы сериализованная форма использовалась с приложением python, которое может запрашивать базу данных через Django api, тогда вам понадобится сериализовать набор запросов с одним объектом. Если, с другой стороны, то, что вам нужно, — это способ повторно раздуть экземпляр модели где-то в другом месте, не касаясь базы данных или не используя Django, тогда вам нужно немного поработать.

Вот что я делаю:

Во-первых, я использую demjson для преобразования. Это было то, что я нашел первым, но это может быть не самое лучшее. Моя реализация зависит от одной из ее функций, но с другими преобразователями должны быть аналогичные способы.

Во-вторых, реализуйте метод json_equivalent для всех моделей, которые могут потребоваться для сериализации. Это волшебный метод для demjson , но, вероятно, вы захотите подумать о том, какую реализацию вы выберете. Идея состоит в том, что вы возвращаете объект, который напрямую конвертируется в json (т.е. Массив или словарь). Если вы действительно хотите сделать это автоматически:

Это не поможет вам, если у вас нет полностью плоской структуры данных (нет ForeignKeys , только числа и строки в базе данных и т.д.). В противном случае вам следует серьезно подумать о правильном способе реализации этого метода.

Модуль json

JSON (JavaScript Object Notation) — простой формат обмена данными, основанный на подмножестве синтаксиса JavaScript. Модуль json позволяет кодировать и декодировать данные в удобном формате.

Кодирование основных объектов Python:

Декодирование (парсинг) JSON:

Основы

json.dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) — сериализует obj как форматированный JSON поток в fp.

Если skipkeys = True, то ключи словаря не базового типа (str, unicode, int, long, float, bool, None) будут проигнорированы, вместо того, чтобы вызывать исключение TypeError.

Если ensure_ascii = True, все не-ASCII символы в выводе будут экранированы последовательностями \uXXXX, и результатом будет строка, содержащая только ASCII символы. Если ensure_ascii = False, строки запишутся как есть.

Если check_circular = False, то проверка циклических ссылок будет пропущена, а такие ссылки будут вызывать OverflowError.

Если allow_nan = False, при попытке сериализовать значение с запятой, выходящее за допустимые пределы, будет вызываться ValueError (nan, inf, -inf) в строгом соответствии со спецификацией JSON, вместо того, чтобы использовать эквиваленты из JavaScript (NaN, Infinity, -Infinity).

Если indent является неотрицательным числом, то массивы и объекты в JSON будут выводиться с этим уровнем отступа. Если уровень отступа 0, отрицательный или «», то вместо этого будут просто использоваться новые строки. Значение по умолчанию None отражает наиболее компактное представление. Если indent — строка, то она и будет использоваться в качестве отступа.

Если sort_keys = True, то ключи выводимого словаря будут отсортированы.

json.dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw) — сериализует obj в строку JSON-формата.

Аргументы имеют то же значение, что и для dump().

json.load(fp, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) — десериализует JSON из fp.

object_hook — опциональная функция, которая применяется к результату декодирования объекта (dict). Использоваться будет значение, возвращаемое этой функцией, а не полученный словарь.

object_pairs_hook — опциональная функция, которая применяется к результату декодирования объекта с определённой последовательностью пар ключ/значение. Будет использован результат, возвращаемый функцией, вместо исходного словаря. Если задан так же object_hook, то приоритет отдаётся object_pairs_hook.

parse_float, если определён, будет вызван для каждого значения JSON с плавающей точкой. По умолчанию, это эквивалентно float(num_str).

parse_int, если определён, будет вызван для строки JSON с числовым значением. По умолчанию эквивалентно int(num_str).

parse_constant, если определён, будет вызван для следующих строк: «-Infinity», «Infinity», «NaN». Может быть использовано для возбуждения исключений при обнаружении ошибочных чисел JSON.

Если не удастся десериализовать JSON, будет возбуждено исключение ValueError.

json.loads(s, encoding=None, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw) — десериализует s (экземпляр str, содержащий документ JSON) в объект Python.

Остальные аргументы аналогичны аргументам в load().

Кодировщики и декодировщики

Класс json.JSONDecoder(object_hook=None, parse_float=None, parse_int=None, parse_constant=None, strict=True, object_pairs_hook=None) — простой декодер JSON.

Выполняет следующие преобразования при декодировании:

JSON Python
object dict
array list
string str
number (int) int
number (real) float
true True
false False
null None

Он также понимает NaN, Infinity, и -Infinity как соответствующие значения float, которые находятся за пределами спецификации JSON.

Класс json.JSONEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)

Расширяемый кодировщик JSON для структур данных Python. Поддерживает следующие объекты и типы данных по умолчанию:

Цукерберг рекомендует:  Вакансии ПОКАЗАТОР - социальная сеть для вещей.
Понравилась статья? Поделиться с друзьями:
Все языки программирования для начинающих