2

Using django rest framework I want to validate fields.

Correct input request:

{
   test_field_a: {test_field_c: 25}, 
   test_field_b: {}
}

My serializers.py (I don't have any associated models and the models.py itself):

from rest_framework import serializers
class TestSerializer(serializers.Serializer):
  test_field_a = serializers.JSONField(label='test_field_a', allow_null=False, required=True)
  test_field_b = serializers.JSONField(label='test_field_b', required=True)
  test_field_c = serializers.IntegerField(label='test_field_c)

Wrong input request (which should state that int field is required) :

{
   test_field_a: {test_field_c: 'wrong'}, 
   test_field_b: {}
} 

Now test_field_a and test_field_b are validated as required. But how to make validation of fields on different levels of the request? (in this case test_field_c)

2 Answers 2

4

JSONField just checks that a field contains correct JSON structure. You need to do it plus check values from this JSON.

There are several ways to do it:

  1. You can write your own custom field type (it's nice if you are planning to do something similar in other serializers);
  2. You can change field validation (try something like this):

    from rest_framework import serializers
    
    class TestSerializer(serializers.Serializer)::
        test_field_a = serializers.JSONField(label='test_field_a', allow_null=False, required=True)
        test_field_b = serializers.JSONField(label='test_field_b', required=True)
    
        def validate_test_field_a(self, value):
            """
            Check that test_field_a .
            """
            if not isinstance(value.get('test_field_c'), int):
               raise serializers.ValidationError("Some error message")
           return value
    
  3. You can try nested validation:

    from rest_framework import serializers
    
    
    class Test1Serializer(serializers.Serializer):
        test_field_c = serializers.IntegerField(label='test_field_c')
    
    
    class TestSerializer(serializers.Serializer):
        test_field_a = Test1Serializer()
        test_field_b = serializers.JSONField(label='test_field_b', required=True)
    
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks! In 3. Is there a way to additionally check if test_field_a is a json type?
@trthhrtz check if it is of type dict
@trthhrtz If you want to work with JSON only, you can specify it in parser_classes attribute or project settings. Then the only possible structure type for test_field_a will be JSON. django-rest-framework.org/api-guide/parsers/…
@AlexK. Actually the parser class just requires that the request payload be in json format. Nothing prevents you from adding integers, strings and other types into json, so adding that parser doesn't mean that even the nested fields will all be json since json iteslf is made of other primary types. And again it would just throw an error if it can't be parse the payload without specifying the erroneous field. Not sure that what's is needed here
@AlexK. We probably didn't understand each other correctly. His question was how to check that test_field_a is of type json and you proposed just setting parser class to json. if `test_field_a' is just a charfield, the parser would still perfectly parse TypeSerializer without any issues thereby failing to validate that it is json.
|
2

The serializer's JSONField does not have a validation for nested fields because it is not meant to nest explicitly declared fields and as far as I know, there is currently no way to specify a json schema to validate it. What you can do is validate the field yourself by declaring a validate_test_field_a validation method.

For example:

    def validate_test_field_a(self, value):
        if 'test_field_c' not in value:
            raise serializers.ValidationError('`test_field_c` is required')
        return value

Generally, if you find yourself needing to validate the nested type inside the JSONField, then it is a sign of bad architecture and you should consider using nested serializers instead. Same applies to using JSONField in the model

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.