I have the following json that I want to deserialize in order to insert data into 3 tables.
{ "id":"game_id", "rated":true, "variant":"standard", "speed":"fast", "perf":"fast", "createdAt": 1234, "lastMoveAt":1234, "status":"resign", "players":{ "white":{ "user":{ "name":"player1", "id":"player1" }, "rating":1000, "ratingDiff":-5 }, "black":{ "user":{ "name":"player2", "id":"player2" }, "rating":1001, "ratingDiff":5 } }, "winner":"black", "opening":{ "eco":"Z99", "name":"my opening", "ply":2 }, "moves":"1, 2, 3, 4", "clock":{ "initial":60, "increment":0, "totalTime":60 } } Here are my models : class User(models.Model): class Meta: ordering = ["id"] id = models.CharField(primary_key=True, max_length=100) name = models.CharField(max_length=100) def __repr__(self): return f"User(id={self.id!r}, name={self.name!r})" class Opening(models.Model): class Meta: ordering = ["eco"] constraints = [ models.UniqueConstraint( fields=["name", "eco"], name="eco_name" ) ] name = models.CharField(max_length=200) eco = models.CharField(max_length=3) def __repr__(self): return f"User(name={self.name!r}, eco={self.eco!r})" class Game(models.Model): class Meta: ordering = ["last_move_at"] id = models.CharField(primary_key=True, max_length=15) rated = models.BooleanField(default=True) variant = models.CharField(max_length=200) speed = models.CharField(max_length=50) perf = models.CharField(max_length=50) created_at = models.IntegerField() last_move_at = models.IntegerField() status = models.CharField(max_length=50) winner = models.CharField(max_length=100) moves = models.TextField(max_length=1000) white_rating = models.IntegerField() white_rating_diff = models.IntegerField() white = models.ForeignKey(User, related_name="white_id", on_delete=models.CASCADE) black_rating = models.IntegerField() black_rating_diff = models.IntegerField() black = models.ForeignKey(User, related_name="black_id", on_delete=models.CASCADE) opening = models.ForeignKey(Opening, related_name="eco_name", on_delete=models.CASCADE) initial_time = models.IntegerField(null=True) increment = models.IntegerField(null=True) total_time = models.CharField(max_length=200) Here are my serializers : class UserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ["id", "name"] class OpeningSerializer(serializers.ModelSerializer): class Meta: model = Opening fields = ["name", "eco"] def create(self, validated_data): return Opening.objects.get_or_create(**validated_data)[0] class GameSerializer(serializers.ModelSerializer): class Meta: model = Game fields = ['id', 'rated', 'variant', 'speed', 'perf', 'created_at', 'last_move_at', 'status', 'winner', 'moves', 'white_rating', 'white_rating_diff', 'white', 'black_rating', 'black_rating_diff', 'black', "opening", 'initial_time', 'increment', 'total_time'] def to_internal_value(self, data): internal_value = {"opening": data.pop("opening")} del data["pgn"] white_data = data.get("players")["white"] internal_value["white"] = white_data["user"] internal_value["white_rating"] = white_data["rating"] internal_value["white_rating_diff"] = white_data["ratingDiff"] black_data = data.pop("players")["black"] internal_value["black"] = black_data["user"] internal_value["black_rating"] = black_data["rating"] internal_value["black_rating_diff"] = black_data["ratingDiff"] internal_value["created_at"] = data.pop("createdAt") internal_value["last_move_at"] = data.pop("lastMoveAt") internal_value["initial_time"] = data.get("clock").get("initial") internal_value["increment"] = data.get("clock").get("increment") internal_value["total_time"] = data.pop("clock").get("totalTime") return {**internal_value, **data} def create(self, validated_data): white = validated_data.pop("white") white_user, is_created = User.objects.get_or_create(id=white["id"], name=white["name"]) black = validated_data.pop("black") black_user, is_created = User.objects.get_or_create(id=black["id"], name=black["name"]) opening = validated_data.pop("opening") opening_model, is_created = Opening.objects.get_or_create(name=opening["name"], eco=opening["eco"]) return Game.objects.get_or_create(white=white_user, black=black_user, opening=opening_model, **validated_data)[0] I have two problems : 1. I don’t know if I am following good practices here. In particular, is it the right use of the "to_internal_value" function ? 2. Sometimes the json I receive contains additional fields, like "moderator": "players":{ "white":{ "user":{ "name":"player1", "id":"player1", **"moderator": True** } } } and my deserialization process fails because it contains an unexpected field. How can I handle it and make it more resilient ? -- You received this message because you are subscribed to the Google Groups "Django REST framework" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-rest-framework+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-rest-framework/f33c38a2-f36d-40d1-8013-2e0fdbceedbdn%40googlegroups.com.