I'm using the following link preview python package in my django 3.2 api. https://github.com/meyt/linkpreview
When I post a link from my frontend flutter app and attempt to preview it, I get the error as stated.
TypeError: Object of type LinkPreview is not JSON serializable
Here are the views.py my flutter app hits :
class PreviewLink(APIView):
permission_classes = (IsAuthenticated, IsNotSuspended)
throttle_scope = 'link_preview'
def post(self, request):
serializer = PreviewLinkSerializer(data=request.data, context={"request": request})
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
link = data.get('link')
user = request.user
link_preview = user.preview_link(link)
return Response(link_preview, status=status.HTTP_200_OK)
class LinkIsPreviewable(APIView):
permission_classes = (IsAuthenticated, IsNotSuspended)
throttle_scope = 'link_preview'
def post(self, request):
serializer = PreviewLinkSerializer(data=request.data, context={"request": request})
serializer.is_valid(raise_exception=True)
data = serializer.validated_data
link = data.get('link')
try:
is_previewable = link_preview(url=link)
except Exception as e:
is_previewable = False
return Response({
'is_previewable': is_previewable
}, status=status.HTTP_200_OK)
The PreviewLinkSerializer class --->
class PreviewLinkSerializer(serializers.Serializer):
link = serializers.CharField(max_length=255, required=True, allow_blank=False)
The link_preview function:
def link_preview(url: str = None,content: str = None,parser: str = "html.parser"):
"""
Get link preview
"""
if content is None:
try:
grabber = LinkGrabber()
content, url = grabber.get_content(url)
except InvalidMimeTypeError:
content = ""
link = Link(url, content)
return LinkPreview(link, parser=parser)
Here is the User class that contains preview_link():
def preview_link(self, link):
return link_preview(url=link)
I have only pasted the relevant code above. The complete code is available in the link I shared.
The problem
If we look into the error message, we might get some useful information:
Here we can see that:
LinkPreviewLooking at your code, I can see that the
link_previewis returning aLinkPreviewobject.Then we have (something like) this in your
LinkIsPreviewable#post()method:which means we're telling Django to serialize a mapping from
strtoLinkPreview, which it doesn't know how to do.The solution
Based on the author's comment under the OP's question on GitHub, there is a
LinkPreview#to_dictmethod which converts aLinkPreviewinstance to a serializabledict.Therefore, if you only need the information returned by that method, you can simply use it.
This way, you'd only need to change one line for each method, so turn:
to
and
into
The old solution
So how do we solve it?
We have to first serialize the
is_previewableand then store it in thedict.I wasn't able to find a serializer for the
LinkPreviewclass in the GitHub repository you provided, therefore you have to write it yourself.Something like these would do:
Note that I only implemented it for the
Generictype, you can do the same for the rest of the source types as well.Then you can use it to serialize
LinkPreviewobjects like this:Now, the
serialized_previewcan be stored in adictand be passed to theResponseconstructor.