Thanks for the clarification -> although it seems like it should actually 
raise a warning or exception to prevent non-deterministic data errors when 
people aren't aware.

Oliver

On Tuesday, April 24, 2018 at 8:20:53 PM UTC-7, Simon Charette wrote:
>
> Hello Olivier,
>
> Since JSON objects can only have string keys[0] I'd suggest you always use 
> strings
> as dict keys on the Python side to avoid having to deal with both cases.
>
> Another solution would to subclass JSONField to override the from_db_value 
> method
> to turn keys into integer when retrieved from the database.
>
> Cheers,
> Simon
>
> [0] 
> https://stackoverflow.com/questions/9304528/why-json-allows-only-string-to-be-a-key#9304820
>
> Le mardi 24 avril 2018 20:21:13 UTC-4, Oliver Zhou a écrit :
>>
>> 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 JSON in string 
>> format? Should I be converting all JSONField fields into string or integers 
>> before trying to manipulate any values in Django?
>>
>> *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]: reload_example.external_ids[str(1234)]
>> Out[160]: {}
>>
>> *Example 2 - Confusing identical key conflict when model is loaded in 
>> memory with both integer and string based keys*
>> 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.
>>
>> First, I create a new model and save some dictionary down to 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 reload the model *
>>
>> 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 replace those values : (I swapped the 567 and the 890)*
>>
>> In [172]: reload_example2.external_ids[1234] = {'890': '567'}
>>
>> *For the time being, now I have two key value pairs in memory for the 
>> same key, just that the older data falls under a string instance of the 
>> key, and both values can be accessed*
>> In [173]: reload_example2.external_ids
>> Out[173]: {1234: {'890': '567'}, u'1234': {u'567': u'890'}}
>>
>>
>> *After I save and then reload the model, I'm unsure which value gets 
>> saved over. (Although in tests it seems like the newest data wins)*
>> In [174]: reload_example2.save()
>> 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.
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/cda0a09f-8a0b-4e63-979f-8191bf60c891%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to