Serializing a Python namedtuple to json

后端 未结 11 1713
梦谈多话
梦谈多话 2020-11-29 18:50

What is the recommended way of serializing a namedtuple to json with the field names retained?

Serializing a namedtuple to json results in only the valu

相关标签:
11条回答
  • 2020-11-29 19:14

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

    Python 2.7+:

    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))
    

    Python 3.6.6+:

    import json
    from typing import TupleName
    
    def json_serializable(cls):
        def as_dict(self):
            yield {name: value for name, value in zip(
                self._fields,
                iter(super(cls, self).__iter__()))}
        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))
    
    0 讨论(0)
  • 2020-11-29 19:18

    I wrote a library for doing this: https://github.com/ltworf/typedload

    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.

    0 讨论(0)
  • 2020-11-29 19:18

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

    0 讨论(0)
  • 2020-11-29 19:19

    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.

    0 讨论(0)
  • 2020-11-29 19:24

    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.

    0 讨论(0)
  • 2020-11-29 19:29

    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)
    {'agent': {'first_name': 'asd',
    'last_name': 'asd',
    'mail': '2@mai.com',
    'id': 1},
    'content': 'text',
    'customer': {'first_name': 'asd',
    'last_name': 'asd',
    'mail': '2@mai.com',
    'phone_number': 123123,
    'id': 1},
    'id': 2,
    'la': 123123,
    'ls': 4512313,
    'media_url': 'h.com',
    'type': 'image'}
    
    0 讨论(0)
提交回复
热议问题