-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Convert ListField error indexes to str #6424
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Before this commit, child validation errors returned from ListField would be held in a dictionary with the list index as an integer key. This commit changes it so that the key is converted to str before being used as a key. The motivation for this is that rapidjson (an alternative python json package) doesn't allow converting dicts with anything other than str keys (i.e., it does not do any type conversion). Other json packages (json, ujson, simplejson) tend to allow this and just do the type conversion themselves. With this fix, json, ujson and simplejson will continue to work as before, but rapidjson will become compatible out-of-the-box without having to process the dictionary before rendering to json. One could perhaps argue that this conversion should rather be done in rapidjson itself, or perhaps in glue/adapter code (e.g. in some RapidJSONRenderer implementation); but then again, this seems like an easy fix that hopefully doesn't break much, and saves a potentially costly tree traversal in the renderer. Existing tests have been updated to match this change in behavior. I guess a new test using rapidjson could be useful, but I don't know what DRF's policy is on integration tests that interface with third-party libraries is.
622d615
to
a5044cf
Compare
Hi @sigvef. So how are you using Happy to chat about it, but going to close this on that basis. Thanks. |
Makes sense, no worries.
Yep, pretty basic custom renderer. The entire implementation: from rest_framework.renderers import BaseRenderer
import rapidjson
class RapidJSONRenderer(BaseRenderer):
media_type = 'application/json'
format = 'json'
def render(self, data, media_type=None, renderer_context=None):
return rapidjson.dumps(
data,
ensure_ascii=False,
datetime_mode=rapidjson.DM_ISO8601,
uuid_mode=rapidjson.UM_CANONICAL,
indent=renderer_context.get('indent', None)).encode()
|
Right, so in there. Just a dictionary comprehension and you're done no? (I'd still see what the upstream folks have to say...) |
That would work (at a slight performance cost). We opted for a parallel reimplementation of ListField with this change that we've been running in production for a couple of weeks. |
Just to add further context, the restriction of string-based object keys is a specification detail of JSON. Other encoding formats may support numeric object keys, so the existing validation behavior is correct. It's up to the renderer in this case to correctly convert the numeric keys to strings. Either, it's the responsibility of rapidjson, some json encoder, or the |
e.g., DRF provides its own encoder for handing non-native JSON types, such as datetimes. https://github.com/encode/django-rest-framework/blob/master/rest_framework/utils/encoders.py |
Hi, this pull request is split out from #6423 . I did some more digging -- initially I thought this was direct bug in DRF, but I was able to trace it back to an integration incompatibility with
rapidjson
. Either way I think it's worth considering, but I can see how there are both arguments for and against doing this :)