Menu
CoddyTech

Error Validasi JSON

Termasuk bagian API JSON dalam perjalanan Django di Coddy. Pelajaran 7 dari 19.

Saat ini, POST tanpa judul menyebabkan crash dengan KeyError, dan Django menjawab 500 Server Error, yang tidak memberi tahu program apa yang harus diperbaiki.

Saat masalahnya ada pada data, jawab dengan 400 Bad Request dan sebutkan apa yang salah dalam JSON, satu pesan untuk setiap field, seperti form Django menyimpan error-nya. Toko buku memeriksa tahun sebuah buku:

errors = {}
year = data.get("year")
if not isinstance(year, int) or year < 0:
    errors["year"] = "Enter the year as a whole number."
if errors:
    return JsonResponse({"errors": errors}, status=400)

Masih ada dua jebakan. Judul yang hanya berisi spasi bukan string kosong, tetapi " ".strip() menghasilkan "". Dan body yang bukan JSON membuat json.loads memunculkan json.JSONDecodeError, yang diubah menjadi 400 oleh try dan except. Status 4xx berarti pemanggil mengirim sesuatu yang salah, sedangkan 5xx berarti kodemu bermasalah.

challenge icon

Tantangan

Sedang

Buat POST /api/tasks/ mengembalikan 400 untuk data yang tidak valid:

  • Tanpa judul, atau hanya berisi spasi: {"errors": {"title": "This field is required."}}, dan tidak ada yang disimpan.
  • Body yang bukan JSON: {"error": "The body is not valid JSON."}.
  • Judul yang valid disimpan tanpa spasi di sekelilingnya.

Tekan Jalankan, lalu di tab Shell: from django.test import Client; print(Client().post("/api/tasks/", {"title": " "}, content_type="application/json").json())

Coba sendiri

import json

from django.http import JsonResponse
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt

from .models import Task


def task_to_dict(task):
    return {
        "id": task.id,
        "title": task.title,
        "done": task.done,
        "priority": task.priority,
    }


def home(request):
    return render(request, "tasks/home.html", {"tasks": Task.objects.all()})


def stats(request):
    data = {
        "total": Task.objects.count(),
        "done": Task.objects.filter(done=True).count(),
    }
    return JsonResponse(data)


@csrf_exempt
def task_list(request):
    if request.method == "POST":
        data = json.loads(request.body)
        task = Task.objects.create(
            title=data["title"],
            priority=data.get("priority", "normal"),
        )
        return JsonResponse(task_to_dict(task), status=201)
    tasks = Task.objects.all()
    done = request.GET.get("done")
    if done == "true":
        tasks = tasks.filter(done=True)
    elif done == "false":
        tasks = tasks.filter(done=False)
    return JsonResponse([task_to_dict(task) for task in tasks], safe=False)


def task_detail(request, pk):
    task = Task.objects.filter(pk=pk).first()
    if task is None:
        return JsonResponse({"error": "Task not found"}, status=404)
    return JsonResponse(task_to_dict(task))

Semua pelajaran di API JSON

Latihan sendiri: Playground Django