[Patchew-devel] [PATCH v3] Text to json convertor for mbox

Paolo Bonzini pbonzini at redhat.com
Sun Apr 29 21:38:04 UTC 2018


On 28/04/2018 18:20, Shubham Jain wrote:
> I noticed two things after sending this. 
> First, we are returning a dictionary rather than a json object for text
> to json converter. Returning a json dump of dictionary gives error of
> date (date time object not json serialisable). Though POST can accept
> dictionary object (I think), I should change the name to get_dictionary
> rather than get_json.

Nicely spotted.  I think the date time object would not be accepted by
the REST API so it would be better to have a real JSON.  You can use
rest_framework itself to format the date/time.  For example

rest_framework.fields.DateTimeField().to_representation(datetime.datetime.now())

gives '2018-04-29T21:19:17.317160'.

Apart from this ussue, the "get_json()" part is more or less okay.
Let's move to the next part and then we'll pick it up again and put it
all together.

You can leave this patch in your branch and go on with the next...

> Second, should we change the format of recipients to
> [{"name":..,"address":..},..] while extracting recipients from mbox? and
> similarly with sender? And the corresponding custom serialiser would
> like something like this
> recipients = AddressSerializer()
> class AddressSerializer(serializers.Field):
>     def to_representation(self,obj):
>         ret = []
>         for item in obj:
>             ret.append({"name":item[0],"address":item[1]})
>         return ret
>     def to_internal_value(self, data):
>         return [[x['name'],x['address']] for x in data]

Yes, indeed!  That's the next step.  A couple things:

- deriving from Field means that you have to implement validation and
that's quite a lot of code.  Instead, you can derive from Serializer,
and the validation is implemented simply by declaring "name" and
"address" fields in the class---just like with any other serializer.
There is only one difference.  For Fields, "to_internal_vlaue_ converts
JSON input to a Python representation, but Serializers keep the
dictionary format after "to_internal_value".  See this example:

    import rest_framework.serializers
    import rest_framework.fields
    class TestSerializer(rest_framework.serializers.Serializer):
        x = rest_framework.serializers.DateTimeField()

    d = {'x': '2018-04-29T21:19:17.317160'}
    s = TestSerializer(data=d)
    s.is_valid()     # -> True
    s.data           # -> {'x': '2018-04-29T21:19:17.317160'}
    s.validated_data # -> x now is the key to a datetime.datetime object

In your case, Serializer's default implementation of "to_internal_value"
is good already, but you'll have to implement "create" , which converts
the Serializer's validated_data to the JSON array.

- you don't need the "for" loops: just declare

    recipients = AddressSerializer(many=True)
    sender = AddressSerializer()

and DRF will take care of serializing/deserializing lists! :)

- there is a special case where ['foo at bar.com', 'foo at bar.com'] leaves
out the "name" key.  So the serializer should behave like this:

    >>> import api.rest
    >>> first = ['Paolo', 'pbonzini at redhat.com']
    >>> s1 = api.rest.AddressSerializer(first)
    >>> data1 = s1.data
    >>> data1
          {'name': 'Paolo', 'address': 'pbonzini at redhat.com'}
    >>> second = ['pbonzini at redhat.com', 'pbonzini at redhat.com']
    >>> s2 = api.rest.AddressSerializer(second)
    >>> data2 = s2.data
    >>> data2
          {'address': 'pbonzini at redhat.com'}
    >>>
    >>> s1 = api.rest.AddressSerializer(data=data1)
    >>> s1.is_valid()
          True
    >>> s1.validated_data
          OrderedDict([('name', 'Paolo'),
                       ('address', 'pbonzini at redhat.com')])
    >>> s1.save()
          ['Paolo', 'pbonzini at redhat.com']
    >>> s2 = api.rest.AddressSerializer(data=data2)
    >>> s2.is_valid()
          True
    >>> s2.validated_data
          OrderedDict([('address', 'pbonzini at redhat.com')])

Now, apply to your tree my patch for JSONField; you can get it with

  patchew -s https://patchew.org/ \
     apply id:20180426083340.9816-1-pbonzini at redhat.com

... and then switching sender and recipients to AddressSerializer should
work with no other changes required.  The above sample interaction can
be easily converted to a testcase.  This will be your next change!

Thanks,

Paolo




More information about the Patchew-devel mailing list