Кодирование вложенного объекта python в JSON

Я хочу кодировать объекты в JSON. Но я не могу понять, как сделать вывод без вытеснения строки.

import json class Abc: def __init__(self): self.name="abc name" def toJSON(self): return json.dumps(self.__dict__, cls=ComplexEncoder) class Doc: def __init__(self): self.abc=Abc() def toJSON(self): return json.dumps(self.__dict__, cls=ComplexEncoder) class ComplexEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, Abc) or isinstance(obj, Doc): return obj.toJSON() else: return json.JSONEncoder.default(self, obj) doc=Doc() print doc.toJSON() 

Результат (дампы возвращают строковое представление, поэтому «экранируются»)

 {"abc": "{\"name\": \"abc name\"}"} 

Я хочу что-то немного другое. Ожидаемый результат

 {"abc": {"name": "abc name"}"} 

Но я не понимаю, как … Любой намек?

заранее спасибо.

  • Преобразует ли json в dict с eval хороший выбор?
  • Преобразование строки даты JSON в дату и время Python
  • HTML и BeautifulSoup: как итеративно разбирать, когда структура не всегда известна заранее?
  • Одинарные и двойные кавычки в JSON
  • Запросы Python: получить атрибуты из возвращенной строки JSON
  • Firebase с использованием числа с плавающей запятой в качестве ключа
  • Как обновить JSON-файл с помощью Python?
  • Добавление данных в json-файл в Python
  • 5 Solutions collect form web for “Кодирование вложенного объекта python в JSON”

    мой предыдущий образец, с другим вложенным объектом и вашими советами:

     import json class Identity: def __init__(self): self.name="abc name" self.first="abc first" self.addr=Addr() def reprJSON(self): return dict(name=self.name, firstname=self.first, address=self.addr) class Addr: def __init__(self): self.street="sesame street" self.zip="13000" def reprJSON(self): return dict(street=self.street, zip=self.zip) class Doc: def __init__(self): self.identity=Identity() self.data="all data" def reprJSON(self): return dict(id=self.identity, data=self.data) class ComplexEncoder(json.JSONEncoder): def default(self, obj): if hasattr(obj,'reprJSON'): return obj.reprJSON() else: return json.JSONEncoder.default(self, obj) doc=Doc() print "Str representation" print doc.reprJSON() print "Full JSON" print json.dumps(doc.reprJSON(), cls=ComplexEncoder) print "Partial JSON" print json.dumps(doc.identity.addr.reprJSON(), cls=ComplexEncoder) 

    дает ожидаемый результат:

     Str representation {'data': 'all data', 'id': <__main__.Identity instance at 0x1005317e8>} Full JSON {"data": "all data", "id": {"name": "abc name", "firstname": "abc first", "address": {"street": "sesame street", "zip": "13000"}}} Partial JSON {"street": "sesame street", "zip": "13000"} 

    Благодарю.

    Итак, непосредственной проблемой является то, что вы передаете json-модулю значение JSON, которое будет закодировано как еще одна строка в значении JSON.

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

    Опираясь на JSON datetime между Python и JavaScript , я бы пошел с чем-то более близким к этому:

     import json class Abc: def __init__(self): self.name="abc name" def jsonable(self): return self.name class Doc: def __init__(self): self.abc=Abc() def jsonable(self): return self.__dict__ def ComplexHandler(Obj): if hasattr(Obj, 'jsonable'): return Obj.jsonable() else: raise TypeError, 'Object of type %s with value of %s is not JSON serializable' % (type(Obj), repr(Obj)) doc=Doc() print json.dumps(doc, default=ComplexHandler) 

    который получает вас:

     ~$ python nestjson.py {"abc": "abc name"} ~$ 

    Это может быть сделано более чистым / безопасным / безопасным (в частности, просто захват __dict__ обычно не рекомендуется делать за пределами отладки / устранения неполадок), но он должен понять __dict__ . Все, что вам нужно, в принципе, это способ получить json-совместимый объект (будь то простая строка или номер, или список или dict) из каждого «узла» в дереве. Этот объект не должен быть уже JSON-сериализованным объектом, который вы делаете.

    Чтобы избежать повторения кода, как в ответе Фреда Лорана, я перегрузил метод __iter__() следующим образом. Это также позволяет «jsonize» элементы списка, datetime и decimal без каких-либо дополнительных зависимостей, просто используйте dict ().

     import datetime import decimal class Jsonable(object): def __iter__(self): for attr, value in self.__dict__.iteritems(): if isinstance(value, datetime.datetime): iso = value.isoformat() yield attr, iso elif isinstance(value, decimal.Decimal): yield attr, str(value) elif(hasattr(value, '__iter__')): if(hasattr(value, 'pop')): a = [] for subval in value: if(hasattr(subval, '__iter__')): a.append(dict(subval)) else: a.append(subval) yield attr, a else: yield attr, dict(value) else: yield attr, value class Identity(Jsonable): def __init__(self): self.name="abc name" self.first="abc first" self.addr=Addr() class Addr(Jsonable): def __init__(self): self.street="sesame street" self.zip="13000" class Doc(Jsonable): def __init__(self): self.identity=Identity() self.data="all data" def main(): doc=Doc() print "-Dictionary- \n" print dict(doc) print "\n-JSON- \n" print json.dumps(dict(doc), sort_keys=True, indent=4) if __name__ == '__main__': main() 

    Выход:

     -Dictionary- {'data': 'all data', 'identity': {'first': 'abc first', 'addr': {'street': 'sesame street', 'zip': '13000'}, 'name': 'abc name'}} -JSON- { "data": "all data", "identity": { "addr": { "street": "sesame street", "zip": "13000" }, "first": "abc first", "name": "abc name" } } 

    Надеюсь, поможет! благодаря

    Я не мог добавить это как комментарий и добавить в качестве ответа. Последний пример Fred был полезен для меня. Мне сказали, что jsonpickle делает это, но не смог установить модуль для правильной установки и запуска. Поэтому здесь используется код. Однако, несмотря на небольшие изменения, у меня было слишком много переменных для добавления вручную к некоторым объектам. Итак, этот маленький цикл упростил:

     def reprJSON(self): d = dict() for a, v in self.__dict__.items(): if (hasattr(v, "reprJSON")): d[a] = v.reprJSON() else: d[a] = v return d 

    Он может использоваться в любом объекте, у которого есть подкласс, который слишком занят, чтобы передать кодировку. Или может стать помощником для всех классов. Это также работает для полного представления JSON массивов-членов, которые содержат другие классы (при условии, что они реализуют repJSON (), конечно).

    Это то, что вы ищете: https://github.com/jsonpickle/jsonpickle

    Он встраивает сериализацию объектов Python и может быть легко расширен для сериализации настраиваемых типов.

    Python - лучший язык программирования в мире.