Search code examples
django-rest-frameworkgetstream-io

How do i serialize objects during enrichment with stream-django and django rest framework?


Im using stream-django with django REST framework and the enriched activities are throwing "not JSON serializable" on the objects returned from enrichment, which is as expected as they have not gone through any serializing.

How do i customize the enrichment process so that it returns a serialized object from my drf serializer and not the object itself?

Some example data, not enriched:

"is_seen": false,
"is_read": false,
"group": "19931_2016-04-04",
"created_at": "2016-04-04T08:53:42.601",
"updated_at": "2016-04-04T11:33:26.140",
"id": "0bc8c85a-fa59-11e5-8080-800005683205",
"verb": "message",
"activities": [
    {
    "origin": null,
    "verb": "message",
    "time": "2016-04-04T11:33:26.140",
    "id": "0bc8c85a-fa59-11e5-8080-800005683205",
    "foreign_id": "chat.Message:6",
    "target": null,
    "to": [
    "notification:1"
    ],
"actor": "auth.User:1",
"object": "chat.Message:6"
}

The view:

def get(self, request, format=None):
    user = request.user
    enricher = Enrich()
    feed = feed_manager.get_notification_feed(user.id)
    notifications = feed.get(limit=5)['results']
    enriched_activities=enricher.enrich_aggregated_activities(notifications)
    return Response(enriched_activities)

Solution

  • I solved it by doing the following:

    property tag on the model that returns the serializer class

    @property
    def activity_object_serializer_class(self):
        from .serializers import FooSerializer
        return FooSerializer
    

    Then used this to serialize the enriched activities. Supports nesting.

    @staticmethod
    def get_serialized_object_or_str(obj):
        if hasattr(obj, 'activity_object_serializer_class'):
            obj = obj.activity_object_serializer_class(obj).data
        else:
            obj = str(obj)  # Could also raise exception here
        return obj
    
    def serialize_activities(self, activities):
        for activity in activities:
            for a in activity['activities']:
                a['object'] = self.get_serialized_object_or_str(a['object'])
                # The actor is always a auth.User in our case
                a['actor'] = UserSerializer(a['actor']).data
        return activities
    

    and the view:

    def get(self, request, format=None):
        user = request.user
        enricher = Enrich()
        feed = feed_manager.get_notification_feed(user.id)
        notifications = feed.get(limit=5)['results']
        enriched_activities = enricher.enrich_aggregated_activities(notifications)
        serialized_activities = self.serialize_activities(enriched_activities)
        return Response(serialized_activities)