0

I need to validate the following JSON:

{
    "monday": [
        //List of MyClass object
    ],
    "tuesday": [
        //List of MyClass Object
    ],
    "wednesday": [
        //List of MyClass Object
    ],
    ......
}

I need to check if it contains any key that is not a day of the week (mondai, thudai for example). Also MyClass is defined as:

class MyClass(models.Model):
    type = models.CharField(unique=True, max_length=20)
    value = models.IntegerField()

The fieldvalue must be a positive integer and cannot exceed 10000. Also, type must be either cost or benefit In Scala I would use the following:

object MyClass {
  val ALLOWED_TYPES = Seq[String]("cost", "benefit")
  implicit val openingHourReads: Reads[OpeningHour] = (
    (JsPath \ "type").read[String].filter(JsonValidationError("Type must be cost or benefit"))(ALLOWED_TYPES.contains(_))  and
      (JsPath \ "value").read[Int](min(1).keepAnd(max(10000)))

    )(MyClass.apply _)

Is there an equivalent approach in Django?

Kha Nguyễn
  • 463
  • 1
  • 4
  • 16

1 Answers1

2

Yes there is a similar approach in django:

Limiting input data on model level (Question#1):

# models.py
from django.core.validators import MaxValueValidator

class MyClass(models.Model):
    VALUE_CHOICES = [
        ('COST', 'cost'),
        ('BENEFIT', 'benefit')
    ]
    class_type = models.CharField(choices=VALUE_CHOICES,unique=True)
    value = models.IntegerField(validators=[MaxValueValidator(limit_value=10000)])

Limiting input data on serializer level (Question#2):

# serializers.py
from .models import MyClass
from rest_framework import serializers
class MyClassSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyClass
        fields = '__all__'

class MainSerializer(serializers.Serializer):
    day = serializers.ChoiceField(choices=['monday', 'tuesday', 'wednesday'])
    my_class = serializers.ListField(child=MyClassSerializer(many=True))

And finally you need to encapsulate your data to make it generic:

# views.py or any other place you like
from .serializers import MainSerializer

your_json = {
    "monday": [
       //List of MyClass object
    ],
    "tuesday": [
        //List of MyClass Object
    ],
    "wednesday": [
        //List of MyClass Object
    ],
    ......
}
json_array = []

for key, value in your_json:
    json_array.append({'day':key, 'my_class':value})

serializer = MainSerializer(data=json_array, many=True)

serializer.is_valid() # this will tell you if your data is valid or not 
Kha Nguyễn
  • 463
  • 1
  • 4
  • 16
engin_ipek
  • 887
  • 1
  • 8
  • 10
  • Hi, thank you for helping me. Still, I have another question. Is it possible to validate the JSON field names, I need to check if it contains any key that is not a day of the week (`mondai`, `thudai` for example) – Kha Nguyễn Jan 14 '20 at 19:42
  • There are serializers in django rest framework. I strongly recommend reading https://www.django-rest-framework.org/api-guide/serializers/. But your data is not consistent, so rather than trying to validate it through serializers, I would make an array of days and check if the json dictionary's keys are in that array. – engin_ipek Jan 14 '20 at 19:53
  • I know the DRF `Serializer`. However, the JSON does not necessarily contain all days of the week so perhaps `Serializer` does not work. Looping through the JSON to validate its field seems like a bad practice here. – Kha Nguyễn Jan 14 '20 at 20:07
  • Can you check the answer again, hope it helps! – engin_ipek Jan 14 '20 at 23:04