This is actually part of the JSON specification 
<https://tools.ietf.org/html/rfc7159#section-4>.  All of the keys must be 
strings.  If you put in an int or float, it will automatically convert it, but 
that is something you have to watch out for since it can lead to data loss.

>>> import json
>>> test = {4: 5, '4': 'a'}
>>> json.loads(json.dumps(test))
{'4': 5} 

> On Apr 24, 2018, at 6:06 PM, Oliver Zhou <oli...@hirevisor.com> wrote:
> 
> Using Django 1.11, Python 2.7, PostGres, and JSONField I'm getting behavior I 
> don't expect.
> 
> It seems when JSONField values are initially saved/accessed in memory, 
> they're python "integers", but when saved to the database and then 
> re-accessed, the values are now in string format.
> 
> What about how Django handles JSONField string vs integers am I missing here? 
> Whats the best way to get deterministic behavior here? 
> Am I supposed to always, say, use json.dumps to work with this stuff in 
> string format? Should I be converting all JSONField values before trying to 
> access any values?
> 
> Example 1 - Basic Problem
> 
> Example Model :
> class ExampleModel(models.Model): 
>     external_ids = JSONField(blank=True, null=True, default=dict)
> 
> My code:
> new_example = ExampleModel.objects.create()
> new_example.external_ids[1234] = {}
> print(new_example.external_ids)
> 
> Output looks like this : 
> {1234: {}}
> 
> 
> I can now access values stored like this :
> In [140]: new_example.external_ids[1234]
> Out[140]: {}
> 
> I will now then save the object to the database
> new_example.save()
> 
> However, when I go back and try to access the fields again, all integer 
> values in the JSON have been converted into strings, and I cannot access them 
> anymore without getting a KeyError
> reload_example = ExampleModel.objects.get(id=1) 
> reload_example.external_ids[1234] 
> In [144]: reload_example.external_ids[1234]
> ---------------------------------------------------------------------------
> KeyError                                  Traceback (most recent call last)
> <ipython-input-147-064b4b6a1511> in <module>()
> ----> 1 reload_example.external_ids[1234]
> KeyError: 1234
> 
> 
> By this time, the integer 1234 has been converted into a string that looks 
> like something like the following :  Why is this?
> In [147]: print(reload_example.external_ids)
> Out[147]: {u'1234': {}}
> 
> Therefore, at this time, I have to do this to access the fields : Whats the 
> correct way to handle this?
> In [160]: c2.external_ids[str(1234)]
> Out[160]: {}
> 
> Example 2 - Non-deterministic Merge Problem - 
> In fact, this creates some other interesting problems for me too, where 
> integer keys and string keys get merged together in uncertain order as well.
> 
> I create a new model - and save some key value pairs down into the JSONField:
> In [164]: example2 = ExampleModel.objects.create()
> In [165]: example2.external_ids
> Out[165]: {}
> In [166]: example2.external_ids[1234] = {'567': '890'}
> In [167]: example2.save()
> In [169]: example2.external_ids
> Out[169]: {1234: {'567': '890'}}
> 
> Then I try to reload the model back into memory :
> 
> In [170]: reload_example2 = ExampleModel.objects.get(id=2)
> In [171]: reload_example2.external_ids
> Out[171]: {u'1234': {u'567': u'890'}}
> 
> Then I try to save a new set of values for key 1234:
> 
> In [172]: reload_example2.external_ids[1234] = {'890': '567'}
> In [173]: reload_example2.external_ids
> Out[173]: {1234: {'890': '567'}, u'1234': {u'567': u'890'}}
> 
> Now it seems like both key value pairs are loaded into memory - just the 
> older one is tracked by a string-ified key, and the new values are tracked by 
> an integer-based key
> In [174]: reload_example2.save()
> 
> Then I save and reload the model again - it seems uncertain which values 
> actually got saved down - whats the expectation here?
> In [175]: reload_example3 = ExampleModel.objects.get(id=2)
> In [176]: reload_example3.external_ids
> Out[176]: {u'1234': {u'890': u'567'}}
> 
> 
> Thanks!
> Oliver
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to django-users+unsubscr...@googlegroups.com 
> <mailto:django-users+unsubscr...@googlegroups.com>.
> To post to this group, send email to django-users@googlegroups.com 
> <mailto:django-users@googlegroups.com>.
> Visit this group at https://groups.google.com/group/django-users 
> <https://groups.google.com/group/django-users>.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/django-users/ae8000bd-e7cb-44a3-9eb6-2c5a3926861e%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/django-users/ae8000bd-e7cb-44a3-9eb6-2c5a3926861e%40googlegroups.com?utm_medium=email&utm_source=footer>.
> For more options, visit https://groups.google.com/d/optout 
> <https://groups.google.com/d/optout>.

Peter of the Norse
rahmc...@radio1190.org



-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/33B399FF-9ACB-4E5C-9711-931F73625CA3%40Radio1190.org.
For more options, visit https://groups.google.com/d/optout.

Reply via email to