djangonauts / django-hstore

PostgreSQL HStore support for Django.
http://django-hstore.readthedocs.io/
Other
517 stars 142 forks source link

ValueError when saving a regular JSON string #137

Closed TehQuila closed 6 years ago

TehQuila commented 8 years ago

Hi, I think I stumbled over a problem with the SerializedDictionaryField.

I found that JSON strings at the root level of a JSON object fail to be saved to the database with a ValueError.

I have the following model

class User(models.Model):
    data = hstore.SerializedDictionaryField(blank=True)

and I use the HStoreSerializer of the django-rest-framework-hstore

class UserSerializer(HStoreSerializer):
    class Meta:
        model = User

When I post the following data to my view

{
    "data": {
        "asdf": "asdf"
    }
}

I get the following error

Environment:
Request Method: POST
Request URL: http://localhost:8000/users

Django Version: 1.8.7
Python Version: 3.4.3
Installed Applications:
('django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.postgres',
 'django_hstore',
 'rest_framework_swagger',
'user')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware')

Traceback:
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
132.              response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/django/views/decorators/csrf.py" in wrapped_view
  58.              return view_func(*args, **kwargs)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/django/views/generic/base.py" in view
  71.               return self.dispatch(request, *args, **kwargs)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/rest_framework/views.py" in dispatch
  466.             response = self.handle_exception(exc)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/rest_framework/views.py" in dispatch
  463.             response = handler(request, *args, **kwargs)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/rest_framework/generics.py" in post
  246.             return self.create(request, *args, **kwargs)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/rest_framework/mixins.py" in create
  20.               serializer.is_valid(raise_exception=True)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/rest_framework/serializers.py" in is_valid
  213.             self._validated_data = self.run_validation(self.initial_data)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/rest_framework/serializers.py" in run_validation
  407.             value = self.to_internal_value(data)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/rest_framework/serializers.py" in to_internal_value
  437.             validated_value = field.run_validation(primitive_value)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/rest_framework/fields.py" in run_validation
  482.             value = self.to_internal_value(data)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/rest_framework/fields.py" in to_internal_value
  1671.          return self.model_field.to_python(data)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/django_hstore/fields.py" in to_python
  341.             return self._deserialize_dict(value)
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/django_hstore/fields.py" in _deserialize_dict
  313.             return dict((k, self._deserialize_value(v)) for k, v in value.items())
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/django_hstore/fields.py" in <genexpr>
  313.             return dict((k, self._deserialize_value(v)) for k, v in value.items())
File "/home/tim/workspace/profiler/venv/lib/python3.4/site-packages/django_hstore/fields.py" in _deserialize_value
  307.             return self.deserializer(value)
File "/usr/lib64/python3.4/json/__init__.py" in loads
  318.             return _default_decoder.decode(s)
File "/usr/lib64/python3.4/json/decoder.py" in decode
  343.             obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib64/python3.4/json/decoder.py" in raw_decode
  361.             raise ValueError(errmsg("Expecting value", s, err.value)) from None

Exception Type: ValueError at /users
Exception Value: Expecting value: line 1 column 1 (char 0)

I tinkered around a bit and I found that if I put an escaped string into the JSON string it works:

{
    "data": {
        "asdf": "\"asdf\""
    }
}

I tried that because I saw that this is done with JSON strings that are in a dict. The following example

{
    "data": {
        "asdf": {
            "asdf": "asdf"
        }
    }
}

results in the hstore field of the database as:

"asdf"=>"{\"asdf\": \"asdf\"}"

I use django-rest-framework 3.3.1, django-rest-framework-hstore 1.3 with django-hstore 1.4.

perrohunter commented 7 years ago

Did you solved this issue?

TehQuila commented 7 years ago

@perrohunter No, sadly the project I used django-hstore in was discontinued so I didn't look into that anymore. I have no further information concerning this issue.