Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Json serialized data having backslashes

I am using rest_framework.response method to send objects of multiple django models. However, the response containts backslashes with quotes. Here is my view:

@api_view()
def myfunctions(request,id):
    responseData = {}
    userObject = TifUser.objects.filter(id=id)
    attendances = Attendance.objects.filter(User=userObject)
    leaves = Leave.objects.filter(User=userObject)
    odds = ODD.objects.filter(User=userObject)
    printjobs = PrintJob.objects.filter(User=userObject)
    issues = Issue.objects.filter(User=userObject)

    #serialize into json
    userObject = serializers.serialize("json", userObject)
    attendances = serializers.serialize("json",attendances)
    leaves = serializers.serialize("json",leaves)
    odds = serializers.serialize("json",odds)
    printjobs = serializers.serialize("json",printjobs)
    issues = serializers.serialize("json",issues)

    #set responseData dictionary values
    responseData['user'] = userObject
    responseData['attendances'] = attendances
    responseData['leaves'] = leaves
    responseData['odds'] = odds
    responseData['printjobs'] = printjobs
    responseData['issues'] = issues
    #responseData['attendances'] = userObject
    return response.Response(responseData)

The json response I am getting is:

{"attendances":"[{\"model\": \"mainApp.attendance\", \"pk\": 5, \"fields\": {\"ArrivalTime\": \"2016-06-27T18:45:46.355Z\", \"DepartureTime\": null, \"User\": 4, \"ArrivalImei\": \"1\", \"DepartureImei\": null, \"Hash\": \"321f059c-4230-417a-adff-f0035097c85d\"}}, {\"model\": \"mainApp.attendance\", \"pk\": 13, \"fields\": {\"ArrivalTime\": \"2016-07-18T15:40:39.943Z\", \"DepartureTime\": null, \"User\": 4, \"ArrivalImei\": \"2\", \"DepartureImei\": null, \"Hash\": \"e61fad3e-8238-46fc-b09b-8b7754d43f3b\"}}]","printjobs":"[{\"model\": \"mainApp.printjob\", \"pk\": 1, \"fields\": {\"User\": 4, \"DateAdded\": \"2016-07-18\", \"Status\": \"disapproved\", \"Person\": 5, \"Level\": \"boss\", \"Client\": \"someone\", \"HandledBy\": \"tester\", \"SanctionedBy\": \"myself\", \"AdvancePayment\": 0, \"FinalPayment\": 1000, \"PaymentNumber\": 1, \"Remarks\": \"something\"}}]","odds":"[]","user":"[{\"model\": \"mainApp.tifuser\", \"pk\": 4, \"fields\": {\"AuthUser\": 7, \"Head\": null, \"Boss\": null, \"ClrLevel\": 1, \"Department\": 1, \"DesignationName\": 1, \"Name\": \"tester\", \"IsRegistered\": true, \"DateOfBirth\": \"1222-11-11\", \"Anniversary\": \"2001-12-22\", \"Mobile\": \"2134567890\", \"gcmDevice\": null, \"FatherName\": \"\", \"MotherName\": \"\", \"PersonalEmail\": \"\", \"Gender\": \"Male\", \"CurrentAddress\": \"\", \"PermanentAddress\": \"\", \"PANNumber\": \"\", \"AadharCardNumber\": null, \"BloodGroup\": \"\", \"MaritalStatus\": \"Married\", \"ProfilePhoto\": \"\", \"Imei\": \"\"}}]","leaves":"[]","issues":"[]"}

Is there any other way to do it? What I understand is, it is encoding the data twice (once in serializers.serialize and then in response.Response). But I dont want that. I want nested objects. Something like this:

{"attendances":[{"model": "mainApp.attendance", "pk": 5, "fields": {"ArrivalTime": "2016-06-27T18:45:46.355Z", "DepartureTime": null, "User": 4, "ArrivalImei": "1",...

Can anyone tell me how to achieve this? Thanks in advance.

like image 369
Nikhil Sardana Avatar asked Jul 26 '16 14:07

Nikhil Sardana


People also ask

Why are there backslashes in JSON?

Those backslashes are escape characters. They are escaping the special characters inside of the string associated with JSON response. You have to use JSON. parse to parse that JSON string into a JSON object.

Is JSON serialized data?

JSON is a format that encodes an object to a string. On the transmission of data or storing is a file, data need to be in byte strings, but as complex objects are in JSON format. Serialization converts these objects into byte strings which is JSON serialization.

How do I remove backslash from JSON response in Python?

Using replace() Function Along with The json. Loads() Function to Remove Backslash from Json String in Python.


2 Answers

I finally managed to solve it. The problem was, when the objects were serialized using serializer.serialize() function, I was getting a string. Whereas I wanted a dict. I had to use json.loads() to convert the string into a dictionary as:

responseData['user'] = json.loads(userObject)

And everything worked as I wanted to. Now, the response is something like:

{
    "attendances": [
        {
            "pk": 5,
            "model": "mainApp.attendance",
            "fields": {
                "DepartureTime": null,
                "Hash": "321f059c-4230-417a-adff-f0035097c85d",
                "ArrivalImei": "1",
                "DepartureImei": null,
                "User": 4,
                "ArrivalTime": "2016-06-27T18:45:46.355Z"
            }
        },
like image 193
Nikhil Sardana Avatar answered Oct 06 '22 15:10

Nikhil Sardana


As you identified, you are double-serializing everything by converting your querysets to JSON strings, adding them to a dict and then passing the dict to response.Response.

Much of the point of using Django REST Framework is that is handles the serialization for you, so the goal should be to avoid serializing to JSON strings yourself in the api view.

To make best use of DRF you need to define a ModelSerializer for each of the models you want to return in the response.

One thing that is confusing in DRF is the terminology. Normally when we talk about "serialization" it means converting objects to a string (i.e. JSON). But in DRF, serializers actually convert complex objects -> primitive objects. So when you use a ModelSerializer to "serialize" your queryset it does not produce a JSON string, but rather primitive python objects (a dict) that can then be serialized, in the conventional sense, to a JSON string without errors. This 'real' serialization is done for you by the Response class.

So I suggest as a starting point:

class TifUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = TifUser


class AttendanceSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Attendance


class LeaveSerializer(serializers.ModelSerializer):
    class Meta:
        model = Leave


class ODDSerializer(serializers.ModelSerializer):
    class Meta:
        model = ODD


class PrintJobSerializer(serializers.ModelSerializer):
    class Meta:
        model = PrintJob

class IssueSerializer(serializers.ModelSerializer):
    class Meta:
        model = Issue


@api_view()
def myfunctions(request, id):
    users = TifUser.objects.filter(id=id)
    user_serializer = TifUserSerializer(users, many=True)

    attendances = Attendance.objects.filter(User=userObject)
    attendance_serializer = AttendanceSerializer(attendancesv, context={'request': request})

    leaves = Leave.objects.filter(User=userObject)
    leave_serializer = LeaveSerializer(leaves, many=True)

    odds = ODD.objects.filter(User=userObject)
    odd_serializer = ODDSerializer(odds, many=True)

    printjobs = PrintJob.objects.filter(User=userObject)
    printjob_serializer = PrintJobSerializer(printjobs, many=True)

    issues = Issue.objects.filter(User=userObject)
    issue_serializer = IssueSerializer(issues, many=True)

    responseData = {}
    responseData['user'] = user_serializer.data
    responseData['attendances'] = attendance_serializer.data
    responseData['leaves'] = leave_serializer.data
    responseData['odds'] = odd_serializer.data
    responseData['printjobs'] = printjob_serializer.data
    responseData['issues'] = issue_serializer.data

    return response.Response(responseData)
like image 36
Anentropic Avatar answered Oct 06 '22 16:10

Anentropic