ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • list comprehension 중복 제거 - Object of type set is not JSON serializable
    Python 2022. 1. 16. 14:56
    class ProductListView(View):
        def get(self, request, *args, **kwargs):
            tagcategory = request.GET.get('tagcategory', None)
            tag         = request.GET.get('tag', None)
            user_type   = request.GET.get('user_type', None)
    
            q = Q()
    
            if user_type:
                q &= Q(user__user_type__name=user_type)
    
            if tagcategory:
                q &= Q(producttag__tag__tag_category__name=tagcategory)
    
            if tag:
                q &= Q(producttag__tag__name=tag)
    
            products = Product.objects.filter(q)
            results  = [
                {
                    'user'             : product.user.nickname,
                    'product_id'       : product.id,
                    'product_name'     : product.name,
                    'main_image'       : product.main_image.image_url,
                    'tag_category_name': [tag.tag_category.name for tag in product.tags.all()],
                    'tag_name'         : [tag.name for tag in product.tags.all() if tag.tag_category.name == tagcategory],
                    'created_date'     : product.created_at.strftime('%Y년 %m월 %d일'),
                    'user_type'        : product.user.user_type.name,
                } for product in products
            ]
            print(results)
            print(products.count())
            return JsonResponse({'results': results}, status=200)

     

    제품 리스트 페이지의 필터링 기능을 구현하고 있었습니다.

    그 과정 중에 위의 results 안에서 'tag_category_name'을 가져올 때 겪었던 어려움에 대해 얘기하려고 합니다.

     

    tag_category_name에는 '대륙', '지역', '테마', '인원'이라는 값이 들어있습니다.

     

    1. 값이 중복되는 점 (ex - ['지역', '테마', '테마', '테마', '테마', '인원', '인원'])

     

    2. [tag.name for tag in product.tags.all() if tag.tag_category.name not in ...]

        - 이런 식으로 if문을 사용하고 싶었으나 list comprehension에 대한 이해가 부족한 것인지

          아니면 방법이 없는 것인지 적절한 비교 대상을 선정하지 못했습니다.

     

    3. set([tag.name for tag in product.tags.all())

        - set을 통해서 중복을 제거하고자 했습니다. 그런데...

          "Object of type set is not JSON serializable" 이런 에러 메시지가 떴습니다...

          이 메시지를 처음 봤을 때 list comprehension을 set으로 바꾸는 과정에서 문제가 발생한 것이라고

          지레 판단한 것이 아쉬운 결정이었습니다.

     

    4. 사실 문제는 마지막인 JsonResponse({'results': results}) 에서 발생한 것이었습니다.

        그래서 찾아보니 Python의 데이터를 JSON화 할 때 데이터 타입이 'set'이어서 생기는 문제라고 생각했습니다.

        배열의 형태로 전달하려고 했으니 set을 리스트로 감싸서 보내면 되지 않을까라는 생각에

        갑자기 기대감이 막 생기기 시작했고 바로 시도해봤습니다.

     

    다행히!! 데이터의 중복 없이 잘 나오는 것을 확인할 수 있었습니다.

     

    1. 'tag_category_name' 값들이 중복되는 문제 발생

     

    rfriend님의 블로그에서 가져온 Python과 JSON의 데이터 변환에 알맞은 데이터 타입을 시각화한 자료입니다.

     

     

    4. TypeError: Object of type is not JSON serializable 에러메세지 line 78인 return JsonResponse에서 에러 발생

     

    중복없이 데이터가 잘 나오는 것을 확인하실 수 있습니다.

     

     

    Python과 JSON의 데이터가 어떤 타입으로 포맷이 이뤄지는지 궁금하시다면

    아래의 블로그에 아주 자세하게 정리되어 있으니 보신다면 많은 도움이 되리라 생각합니다.

     

    https://rfriend.tistory.com/474

     

    [Python] Python으로 JSON 데이터 읽고 쓰기 (Read and Write JSON data by Python)

    json.org의 JSON 소개 내용에 따르면, JSON (JavaScript Object Notation) 은 XML, YAML 과 함께 효율적으로 데이터를 저장하고 교환(exchange data)하는데 사용하는 텍스트 데이터 포맷 중의 하나입니다. JSON은..

    rfriend.tistory.com

     

    'Python' 카테고리의 다른 글

    날짜 입력 및 D-Day 계산  (0) 2022.04.12
    Python shell - help 기능  (0) 2022.01.16
    UUID vs CharField의 max_length  (0) 2022.01.02
    Python dictionary get 메소드 vs Django objects get 메소드  (0) 2022.01.02
    Python 용어 정리  (0) 2021.12.15

    댓글

Designed by Tistory.