Inflearn Community Q&A
DjangoJSONEncoder에서 언급하신 재귀적 로직의 개념
Resolved
Written on
·
301
·
Edited
0
class MyJSONEncoder(DjangoJSONEncoder):
def default(self, obj):
if isinstance(obj, QuerySet):
return tuple(obj)
elif isinstance(obj, Post):
return {'id': obj.id, 'title': obj.title, 'content': obj.content}
elif hasattr(obj, 'as_dict'):
return obj.as_dict()
return super().default(obj)JSON 직렬화 강의에서 위의 구문의 return tuple(obj) 이 실행될 경우 재귀적으로 default 메서드를 탄다고 말씀하셨는데 어떤 원리인지 이해를 하지 못했습니다.
튜플로 변환될 때 어떻게 MyJSONEncoder가 이를 인지하고 작동하는지 여쭤봅니다.
Answer 1
2
안녕하세요.
MyJSONEncoder에 의해서 직렬화 과정 중에, 직렬화 대상에서 각 항목마다 default 메서드를 호출해서 직렬화를 수행합니다.
obj가 만약 QuerySet 객체로서
Post(title="제목1) 과 Post(title="제목2"), 그리고 Post(title="제목3") 를 가지고 있다면
tuple(obj)의 반환값으로서, 튜플인
(Post(title="제목1"), Post(title="제목2"), Post(title="제목3"))
을 반환하게 됩니다.
그러면, 반환값인 튜플에 대해서 다시 default 메서드가 호출되며 인자로 전달이 될 것이구요.
튜플에 대해서는 다시 default 메서드를 호출하게 될 것입니다.

위 코드에서 튜플은 첫번째 if, 두번째 elif, 세번째 elif 조건에 부합되지 않고 super().default(obj) 에 의해서 처리될 것이구요. 파이썬 기본 타입이니 잘 처리될 겁니다.
이제 튜플에서 가지고 있는 각 값들에 대해서 default 메서드가 각각 호출될 것입니다.
그러면 default(Post(title="제목1")) 이 호출될 것이고, elif instance(obj, Post) 조건에 부합되어 {"id": obj.id, "title": obj.title, "content": obj.content}) 를 반환하겠네요.
그리고, 두번째 Post 인스턴스와 세번째 Post 인스턴스에 대해서도 동일하게 처리할 것입니다.
이해에 도움이 되셨을 지 모르겠습니다.
살펴보시고 댓글 남겨주세요.
화이팅입니다. :-)
제가 설명드릴 수 있는 것은 각 값에 대해서 default 메서드를 통해 변환을 수행한다는 정도 일뿐, 세부구현에 대해서는 저도 정확히 알지는 못 합니다.
세부 구현이 궁금하시다면, cpython의 Lib/json/encoders.py 파일에서 JSONEncoder 클래스의 encode 메서드와 iterencode 메서드를 살펴보시면 도움이 되실 듯 합니다.
cpython/encoder.py at 3.11 · python/cpython · GitHub
이때, 단순히 코드만 보시기보다 디버거를 통해 변환과정을 하나씩 따라가보시면 이해하시는 데에 도움이 되시지 않을까 싶습니다.
화이팅입니다. :-)






안녕하세요, 상세한 답변 너무나 감사드립니다. 다만 제가 이해도가 낮아서 인지 질문 내용이 올바로 전달되지 못하였던 것 같습니다.
제가 궁금하였던 내용은 답변에서도 언급하셨던 '반환값인 튜플에 대해서 다시 default 메서드가 호출' 되는 원리에 대해서 입니다.
만약
QuerySet타입에 해당하여 튜플로 변환된 값이 리턴된다면default메서드가 종료될 텐데, 어떤 원리로 다시default메서드가 다시 호출되어 튜플의 각 항목에 대해 실행 될 수 있는지 여쭙고자 하였습니다.다시 한 번 살펴봐 주시면 정말 감사하겠습니다!