JSON에서 중첩된 python 개체를 인코딩하는 중
오브젝트를 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"}"}
하지만 어떻게 해야 할지...힌트 있나요?
잘 부탁드립니다.
다른 중첩된 오브젝트와 당신의 조언이 포함된 이전 샘플:
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 값의 다른 문자열로 인코딩됩니다.
더 큰 문제는 당신이 이걸 너무 복잡하게 만들고 있다는 거예요.
Python과 JavaScript 사이의 JSON datetime을 바탕으로 다음과 같은 것을 선택하겠습니다.
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__
일반적으로 외부 디버깅/트러블 슈팅에서는 권장되지 않지만, 요점을 이해시킬 수 있을 것입니다.기본적으로 트리의 각 "노드"에서 json 호환 객체(단순 문자열, 숫자, 목록 또는 딕트)를 가져오는 방법만 있으면 됩니다.이 오브젝트는 이미 JSON 시리얼화된 오브젝트일 수 없습니다.이러한 오브젝트를 실행하고 있습니다.
Fred Laurent의 답변에서처럼 코드가 반복되지 않도록 하기 위해 나는 오버로드했다.__iter__()
방법은 다음과 같습니다.또한 datetime 및 decimal 요소, datetime 및 decimal 요소도 dict()를 사용하여 'jsonize'할 수 있습니다.
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"
}
}
도움이 됐으면 좋겠다!감사해요.
다른 모든 솔루션은 효과가 있다고 생각되지만, 실제로는 보일러 플레이트 코드가 많이 포함되어 있는 것을 알 수 있습니다.목표는 네스트된 비단뱀 오브젝트만 인코딩하는 것입니다.
기사에서 당신이 요청한 것과 정확히 일치하지만 보일러 플레이트 코드가 없는 우아한 해결책을 찾았습니다.디시리얼라이제이션 부품도 무료로 사용할 수 있기 때문에 먼저 정확한 질문에 대한 해결책을 보여준 후 디시리얼라이제이션이 작동하는 더 깨끗한 버전을 알려드리겠습니다.
질문에 대한 정확한 해결 방법
import json
class Abc(object):
def __init__(self):
self.name = "abc name"
class Doc(object):
def __init__(self):
self.abc = Abc()
doc = Doc()
# Serialization
json_data = json.dumps(doc, default=lambda o: o.__dict__)
print(json_data)
그러면 원하는 위치에 정확하게 출력됩니다.
{"abc": {"name": "abc name"}}
시리얼화와 시리얼화를 가능하게 하는 보다 우아한 솔루션
import json
class Abc(object):
def __init__(self, name: str):
self.name = name
class Doc(object):
def __init__(self, abc):
self.abc = abc
abc = Abc("abc name")
doc = Doc(abc)
# Serialization
json_data = json.dumps(doc, default=lambda o: o.__dict__)
print(json_data)
# De-serialization
decoded_doc = Doc(**json.loads(json_data))
print(decoded_doc)
print(vars(decoded_doc))
다음과 같이 출력됩니다.
{"abc": {"name": "abc name"}}
<__main__.Doc object at 0x7ff75366f250>
{'abc': {'name': 'abc name'}}
기본 람다 함수를 합니다.json_data = json.dumps(doc, default=lambda o: o.__dict__)
.
나는 이것을 댓글로 추가하지 못하고 답변으로 추가하지 못했다.프레드의 최종 샘플은 나에게 유용했다.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 프레젠테이션에도 유효합니다(물론 reprJSON()을 실장하고 있는 한).
좀 더 복잡한 연재에는 2022년에 출판된 jsons를 사용합니다.
Python 개체를 dicts 또는 (JSON) 문자열로 변환한 후 되돌리기
개체를 변경할 필요가 없습니다.
커스터마이즈와 확장이 용이함
데이터 클래스, 특성 및 POPO와 함께 작동
pip install jsons class Person: name:str birthday:datetime personObject = Person("Tony", date_of_birth) import jsons json_data = jsons.dumps(personObject, indent=4)
찾으시는 제품은 다음과 같습니다.https://github.com/jsonpickle/jsonpickle
Python 객체의 중첩된 직렬화를 수행하며, 쉽게 확장하여 사용자 지정 유형을 직렬화할 수 있습니다.
언급URL : https://stackoverflow.com/questions/5160077/encoding-nested-python-object-in-json
'programing' 카테고리의 다른 글
폴리머 원소와 각도 지향성 (0) | 2023.03.10 |
---|---|
타이프 스크립트 및 재스트:시뮬레이션된 함수의 유형 오류 방지 (0) | 2023.03.10 |
Python용 cx_Oracle 설치 (0) | 2023.03.10 |
Oracle에서 톱1을 달성하려면 어떻게 해야 합니까? (0) | 2023.03.10 |
Oracle 포트를 포트 8080에서 변경 (0) | 2023.03.10 |