djangorestframework-camel-case icon indicating copy to clipboard operation
djangorestframework-camel-case copied to clipboard

Ignore UUID in parser

Open jpsuozzi1 opened this issue 1 year ago • 1 comments

I am trying to use the CamelCaseJSONParser on an api that takes in an object where some of the keys are dynamic UUID values. I've come across an issue where the parser underscore-izes these UUID values resulting in invalid UUIDs. I can get around it by using ignore_fields, but I feel that UUIDs don't ever need to be underscore-ized.

I'm able to fix this issue by overriding the underscoreize util like so:

def underscoreize(data, **options):
    from uuid import UUID
    
    ignore_fields = options.get("ignore_fields") or ()
    ignore_keys = options.get("ignore_keys") or ()
    if isinstance(data, dict):
        new_dict = {}
        if type(data) == MultiValueDict:
            new_data = MultiValueDict()
            for key, value in data.items():
                new_data.setlist(camel_to_underscore(key, **options), data.getlist(key))
            return new_data
        for key, value in _get_iterable(data):
            if isinstance(key, str):
                new_key = camel_to_underscore(key, **options)
                # START CHANGES
                try:
                    UUID(key)
                except ValueError:
                    # key is not a UUID, so it's okay to add underscores
                    new_key = camel_to_underscore(key, **options)
                else:
                    new_key = key
                # END CHANGES
            else:
                new_key = key

            if key not in ignore_fields and new_key not in ignore_fields:
                result = underscoreize(value, **options)
            else:
                result = value
            if key in ignore_keys or new_key in ignore_keys:
                new_dict[key] = result
            else:
                new_dict[new_key] = result

        if isinstance(data, QueryDict):
            new_query = QueryDict(mutable=True)
            for key, value in new_dict.items():
                new_query.setlist(key, value)
            return new_query
        return new_dict
    if is_iterable(data) and not isinstance(data, (str, File)):
        return [underscoreize(item, **options) for item in data]

    return data

jpsuozzi1 avatar Jul 24 '23 20:07 jpsuozzi1

@vbabiy would you take a PR on this?

banagale avatar Jan 12 '24 20:01 banagale