Python namedtuple to json

Serializing a Python namedtuple to json

This is pretty tricky, since namedtuple() is a factory which returns a new type derived from tuple . One approach would be to have your class also inherit from UserDict.DictMixin , but tuple.__getitem__ is already defined and expects an integer denoting the position of the element, not the name of its attribute:

At its heart the namedtuple is an odd fit for JSON, since it is really a custom-built type whose key names are fixed as part of the type definition, unlike a dictionary where key names are stored inside the instance. This prevents you from «round-tripping» a namedtuple, e.g. you cannot decode a dictionary back into a namedtuple without some other a piece of information, like an app-specific type marker in the dict , which is a bit hacky.

This is not ideal, but if you only need to encode namedtuples into dictionaries, another approach is to extend or modify your JSON encoder to special-case these types. Here is an example of subclassing the Python json.JSONEncoder . This tackles the problem of ensuring that nested namedtuples are properly converted to dictionaries:

from collections import namedtuple from json import JSONEncoder class MyEncoder(JSONEncoder): def _iterencode(self, obj, markers=None): if isinstance(obj, tuple) and hasattr(obj, '_asdict'): gen = self._iterencode_dict(obj._asdict(), markers) else: gen = JSONEncoder._iterencode(self, obj, markers) for chunk in gen: yield chunk class foobar(namedtuple('f', 'foo, bar')): pass enc = MyEncoder() for obj in (foobar('a', 1), ('a', 1), ): print enc.encode(obj) ["a", 1] > 

Similar question

Here is my take on the problem. It serializes the NamedTuple, takes care of folded NamedTuples and Lists inside of them

def recursive_to_dict(obj: Any) -> dict: _dict = <> if isinstance(obj, tuple): node = obj._asdict() for item in node: if isinstance(node[item], list): # Process as a list _dict[item] = [recursive_to_dict(x) for x in (node[item])] elif getattr(node[item], "_asdict", False): # Process as a NamedTuple _dict[item] = recursive_to_dict(node[item]) else: # Process as a regular element _dict[item] = (node[item]) return _dict 

Dim 481

Читайте также:  Not bold html code

simplejson.dump() instead of json.dump does the job. It may be slower though.

This is an old question. However:

A suggestion for all those with the same question, think carefully about using any of the private or internal features of the NamedTuple because they have before and will change again over time.

For example, if your NamedTuple is a flat value object and you’re only interested in serializing it and not in cases where it is nested into another object, you could avoid the troubles that would come up with __dict__ being removed or _as_dict() changing and just do something like (and yes this is Python 3 because this answer is for the present):

from typing import NamedTuple class ApiListRequest(NamedTuple): group: str="default" filter: str="*" def to_dict(self): return < 'group': self.group, 'filter': self.filter, >def to_json(self): return json.dumps(self.to_dict()) 

I tried to use the default callable kwarg to dumps in order to do the to_dict() call if available, but that didn’t get called as the NamedTuple is convertible to a list.

The jsonplus library provides a serializer for NamedTuple instances. Use its compatibility mode to output simple objects if needed, but prefer the default as it is helpful for decoding back.

It recursively converts the namedTuple data to json.

print(m1) ## Message(id=2, agent=Agent(id=1, first_name='asd', last_name='asd', mail='2@mai.com'), customer=Customer(id=1, first_name='asd', last_name='asd', mail='2@mai.com', phone_number=123123), type='image', content='text', media_url='h.com', la=123123, ls=4512313) def reqursive_to_json(obj): _json = <> if isinstance(obj, tuple): datas = obj._asdict() for data in datas: if isinstance(datas[data], tuple): _json[data] = (reqursive_to_json(datas[data])) else: print(datas[data]) _json[data] = (datas[data]) return _json data = reqursive_to_json(m1) print(data) , 'content': 'text', 'customer': , 'id': 2, 'la': 123123, 'ls': 4512313, 'media_url': 'h.com', 'type': 'image'> 

Tolgahan ÜZÜN 423

There is a more convenient solution is to use the decorator (it uses the protected field _fields ).

import json from collections import namedtuple, OrderedDict def json_serializable(cls): def as_dict(self): yield OrderedDict( (name, value) for name, value in zip( self._fields, iter(super(cls, self).__iter__()))) cls.__iter__ = as_dict return cls #Usage: C = json_serializable(namedtuple('C', 'a b c')) print json.dumps(C('abc', True, 3.14)) # or @json_serializable class D(namedtuple('D', 'a b c')): pass print json.dumps(D('abc', True, 3.14)) 
import json from typing import TupleName def json_serializable(cls): def as_dict(self): yield cls.__iter__ = as_dict return cls # Usage: @json_serializable class C(NamedTuple): a: str b: bool c: float print(json.dumps(C('abc', True, 3.14)) 

It’s impossible to serialize namedtuples correctly with the native python json library. It will always see tuples as lists, and it is impossible to override the default serializer to change this behaviour. It’s worse if objects are nested.

Better to use a more robust library like orjson:

import orjson from typing import NamedTuple class Rectangle(NamedTuple): width: int height: int def default(obj): if hasattr(obj, '_asdict'): return obj._asdict() rectangle = Rectangle(width=10, height=20) print(orjson.dumps(rectangle, default=default)) 

It can go from and to named-tuple and back.

It supports quite complicated nested structures, with lists, sets, enums, unions, default values. It should cover most common cases.

edit: The library also supports dataclass and attr classes.

It looks like you used to be able to subclass simplejson.JSONEncoder to make this work, but with the latest simplejson code, that is no longer the case: you have to actually modify the project code. I see no reason why simplejson should not support namedtuples, so I forked the project, added namedtuple support, and I’m currently waiting for my branch to be pulled back into the main project. If you need the fixes now, just pull from my fork.

EDIT: Looks like the latest versions of simplejson now natively support this with the namedtuple_as_object option, which defaults to True .

If it’s just one namedtuple you’re looking to serialize, using its _asdict() method will work (with Python >= 2.7)

>>> from collections import namedtuple >>> import json >>> FB = namedtuple("FB", ("foo", "bar")) >>> fb = FB(123, 456) >>> json.dumps(fb._asdict()) '' 

benselme 3107

  • extract each ‘thing’ from json file using python for later use
  • Fetch json value correctly and convert into integers using python3 and upload directly into database but in python code there is some error generated
  • Json schema file will not execute in BigQuery Python API
  • Parse config file and create json object using Python
  • function to change json file timestamp format to datetime in python
  • Find the value of at a specific part in JSON with Python
  • Convert repetitive pattern into JSON file with multiple arrays in Python
  • Is there a way of writing ‘_tkinter.tkapp objects’ to a file by using pickle, json or the like? — python tkinter
  • Python JSON Object append
  • Why Is Python JSON serialization so «involved» compared to some other languages
  • Python Json Parsing WildCards/Regex
  • im working with foursquare library in python 3 and trying to convert my query which is a python dictionary into json and encode it
  • Python SQLAlchemy and Postgres — How to search using substring in json value
  • Python JSON dump formatting escaping quotes
  • Decoding JSON file in python with double quotes in value
  • Editing a JSON file with new information in Python
  • How to properly do an AWS Lambda API Post Request with JSON file using Python
  • Getting the required data from a Nested Json using python
  • How to populate a json file from a list in python
  • Python results to JSON

More Query from same tag

  • pip install error setup.py egg_info
  • Python: Using openssl via subprocess to decrypt with a variable password
  • How to write more Pythonic Code
  • How do I set up the values for the x axis in matplot in python?
  • Creating a dictionary from a dictionary using a tuple Python
  • Iterate over values and keys in multiple dictionaries stored in list
  • Recursive Function Inside of a Function
  • Selector.xpath().get() returns all elements after xpath target
  • Python double while loop not working, can’t figure why
  • How to use cvxopt with DSDP?
  • Guide on using different types of variables in a python class?
  • Get data from API using Python and load into Azure SQL Data Warehouse using Azure Data Factory
  • Create line plot on secondary y axis on top of heatmap draw line on wrong x-axis
  • Linked List Class __str__ function
  • SQLAlchemy | Limit join result to one row for one-to-many relationship
  • Comparing files using vector space model
  • PyDot node label with subscript
  • Comparing things in python
  • zooming with NavigationToolbar does not work in matplotlib with pyqt
  • How to add multiple effects to a picture such as contrast and brightness at the same time
  • How to include class from another file(in another folder) — python
  • Function Call Operator Precedence
  • Confused about imports and evals — Python
  • wxPython/ReportLab: How to create and open a .pdf file on button clicked
  • Reloading sources of a CherryPy application behind Apache using Mod_WSGI
  • Python menu-driven programming
  • How to pick the best learning rate and optimizer using LearningRateScheduler
  • How to get upper paths from a single path?
  • How to set focus at one random window when there can show up one window from three different
  • Reading CSV file with python
  • bsddb3.db.DBRunRecoveryError
  • Iterate over multiple generators (file handles)
  • How to compare and merge two files in python
  • Having python display errors in window
  • virtualenv gcc error

Источник

Оцените статью