클래스 인스턴스의 JSON 문자열 표현을 만들려고하는데 어려움이 있습니다. 클래스가 다음과 같이 구축되었다고 가정 해 봅시다.
class testclass:
value1 = "a"
value2 = "b"
json.dumps를 다음과 같이 호출합니다.
t = testclass()
json.dumps(t)
테스트 클래스가 JSON 직렬화 가능하지 않다고 말하고 실패했습니다.
TypeError: <__main__.testclass object at 0x000000000227A400> is not JSON serializable
또한 pickle 모듈을 사용해 보았습니다.
t = testclass()
print(pickle.dumps(t, pickle.HIGHEST_PROTOCOL))
또한 클래스 인스턴스 정보는 제공하지만 클래스 인스턴스의 직렬화 된 내용은 제공하지 않습니다.
b'\x80\x03c__main__\ntestclass\nq\x00)\x81q\x01}q\x02b.'
내가 뭘 잘못하고 있죠?
답변
기본 문제점은 JSON 인코더 json.dumps()
가 기본적으로 모든 내장 유형의 제한된 오브젝트 유형 세트를 직렬화하는 방법 만 알고 있다는 것입니다. 여기에 나열하십시오 : https://docs.python.org/3.3/library/json.html#encoders-and-decoders
좋은 해결책 중 하나는 클래스를 상속 JSONEncoder
하고 구현하는 것입니다.JSONEncoder.default()
함수 해당 함수가 클래스에 맞는 JSON을 생성하도록하는 것입니다.
간단한 해결책은 해당 인스턴스 json.dumps()
의 .__dict__
멤버 를 호출 하는 것 입니다. 그것은 표준 파이썬 dict
이며 클래스가 단순하면 JSON 직렬화 가능합니다.
class Foo(object):
def __init__(self):
self.x = 1
self.y = 2
foo = Foo()
s = json.dumps(foo) # raises TypeError with "is not JSON serializable"
s = json.dumps(foo.__dict__) # s set to: {"x":1, "y":2}
위의 접근 방식은이 블로그 게시물에서 설명합니다.
__dict__를 사용하여 임의의 Python 객체를 JSON으로 직렬화
답변
시험해 볼 수있는 한 가지 방법이 있습니다.
json.dumps()
알 수없는 유형에 대해 사용자 정의 직렬 변환기 기능을 지정할 수 있는 선택적 매개 변수 기본값 을 사용할 수 있습니다.
def serialize(obj):
"""JSON serializer for objects not serializable by default json code"""
if isinstance(obj, date):
serial = obj.isoformat()
return serial
if isinstance(obj, time):
serial = obj.isoformat()
return serial
return obj.__dict__
처음 두 경우는 날짜 및 시간 직렬화 obj.__dict__
에 해당하며 다른 객체에 대해서는 반환됩니다.
최종 통화는 다음과 같습니다.
json.dumps(myObj, default=serialize)
컬렉션을 직렬화하고 전화를 원하지 않을 때 특히 좋습니다. __dict__
모든 객체에 대해 명시 적으로 . 여기 자동으로 완료됩니다.
지금까지 당신의 생각을 기대하면서 저를 위해 아주 잘했습니다.
답변
함수 default
에서 명명 된 매개 변수를 지정할 수 있습니다 json.dumps()
.
json.dumps(obj, default=lambda x: x.__dict__)
설명:
``default(obj)`` is a function that should return a serializable version
of obj or raise TypeError. The default simply raises TypeError.
(Python 2.7 및 Python 3.x에서 작동)
참고 :이 경우 질문의 예와 같이 변수가 instance
아닌 class
변수가 필요합니다. (나는 asker class instance
가 수업의 대상이 될 것이라고 가정하고 있다)
나는 @phihag의 답변 here 에서 이것을 처음 배웠습니다 . 그것이 작업을 수행하는 가장 간단하고 깨끗한 방법이라는 것을 알았습니다.
답변
나는 단지 :
data=json.dumps(myobject.__dict__)
이것은 정답이 아니며 복잡한 객체 클래스가 있으면 모든 것을 얻지는 못할 것입니다. 그러나 나는 이것을 간단한 객체 중 일부에 사용합니다.
정말 잘 작동하는 것은 OptionParser 모듈에서 얻는 “options”클래스입니다. 여기에 JSON 요청 자체가 있습니다.
def executeJson(self, url, options):
data=json.dumps(options.__dict__)
if options.verbose:
print data
headers = {'Content-type': 'application/json', 'Accept': 'text/plain'}
return requests.post(url, data, headers=headers)
답변
jsonpickle 사용
import jsonpickle
object = YourClass()
json_object = jsonpickle.encode(object)
답변
JSON은 실제로 임의의 파이썬 객체를 직렬화하기위한 것이 아닙니다. dict
객체 를 직렬화하는 데는 좋지만 pickle
모듈은 실제로 일반적으로 사용해야합니다. 의 출력 pickle
은 실제로 사람이 읽을 수는 없지만 잘 피해야합니다. JSON 사용을 고집한다면 jsonpickle
흥미로운 하이브리드 방식 인 모듈을 확인할 수 있습니다 .
답변
정교한 클래스가 아닌 직렬화를위한 두 가지 간단한 함수는 다음과 같습니다.
코드 조정없이 클래스에 새 멤버를 추가 할 수 있기 때문에 구성 유형에 사용합니다.
import json
class SimpleClass:
def __init__(self, a=None, b=None, c=None):
self.a = a
self.b = b
self.c = c
def serialize_json(instance=None, path=None):
dt = {}
dt.update(vars(instance))
with open(path, "w") as file:
json.dump(dt, file)
def deserialize_json(cls=None, path=None):
def read_json(_path):
with open(_path, "r") as file:
return json.load(file)
data = read_json(path)
instance = object.__new__(cls)
for key, value in data.items():
setattr(instance, key, value)
return instance
# Usage: Create class and serialize under Windows file system.
write_settings = SimpleClass(a=1, b=2, c=3)
serialize_json(write_settings, r"c:\temp\test.json")
# Read back and rehydrate.
read_settings = deserialize_json(SimpleClass, r"c:\temp\test.json")
# results are the same.
print(vars(write_settings))
print(vars(read_settings))
# output:
# {'c': 3, 'b': 2, 'a': 1}
# {'c': 3, 'b': 2, 'a': 1}