How to Create Nested JSON in Django REST APIs
Tags: django, rest, api, json
Published: 2022-04-01 18:39:13

## Content

- [Introduction](#introduction)
- [My Code as an Example](#my-code-as-an-example)
- [Resulting JSON](#resulting-json)
- [Helpful Links](#helpful-links-section)

## [Introduction](#content)

&emsp; Nesting JSON with the [Django REST Framework](https://www.django-rest-framework.org/) is not intuitive, but it is approachable once learned. Utilize the `serializers.SerializerMethodField()` from the `rest_framework`. By default, this method will call a method that begins with `get_{your_variable_name}`. From here, [Django's QuerySet API](https://docs.djangoproject.com/en/4.0/ref/models/querysets/#django.db.models.query.QuerySet) can help you reduce multiple lines of a SQL into a single line of Python.

## [My Code as an Example](#content)

```python
from django.db.models import QuerySet
from rest_framework import serializers
from skilltree.models import SkillTrees, SkillTreeHexagons, SkillTreePaths, SkillTreeHexagonNotes
from drf_queryfields import QueryFieldsMixin

class SkillTreesSerializer(QueryFieldsMixin, serializers.ModelSerializer):
    class Meta:
        model = SkillTrees
        fields = ('__all__')
    paths = serializers.SerializerMethodField()
    hexagons = serializers.SerializerMethodField()
    hex_string_list = serializers.SerializerMethodField()

    def get_hexagons(self, obj: SkillTrees) -> QuerySet:
        '''
        Get all hex ids that have the skill_tree_id
        The object is the SkillTrees instance
        For example, print(obj.skill_tree_id) will print each skill tree instance's skill_tree_id
        '''
        hexagons: QuerySet = SkillTreeHexagons.objects.filter(
            skill_tree_id=obj.skill_tree_id).values()
        return hexagons

    def get_paths(self, obj: SkillTrees) -> QuerySet:
        '''Get all hex ids that have the skill_tree_id'''
        paths: QuerySet = SkillTreePaths.objects.filter(
            skill_tree_id=obj.skill_tree_id).values()
        return paths

    def get_hex_string_list(self, obj: SkillTrees) -> QuerySet:
        '''Collect all hex string ids'''
        hex_string_ids_obj: QuerySet = SkillTreeHexagons.objects.filter(
            skill_tree_id=obj.skill_tree_id).values_list('hex_string')
        return hex_string_ids_obj
```

## [Resulting JSON](#content)

```json
{
  "skill_tree_id": 3,
  "paths": [
    {
      "path_id": 1,
      "skill_tree_id": 3,
      "starting_hex_q": 0,
      "starting_hex_r": 0,
      "starting_hex_s": 0,
      "ending_hex_q": 2,
      "ending_hex_r": 0,
      "ending_hex_s": -2,
      "starting_hex_string": "0,0,0",
      "ending_hex_string": "2,0,-2"
    },
    {
      "path_id": 2,
      "skill_tree_id": 3,
      "starting_hex_q": 0,
      "starting_hex_r": 0,
      "starting_hex_s": 0,
      "ending_hex_q": 0,
      "ending_hex_r": 2,
      "ending_hex_s": -2,
      "starting_hex_string": "0,0,0",
      "ending_hex_string": "0,2,-2"
    }
  ],
  "hexagons": [
    {
      "hex_id": 1,
      "note_id": null,
      "hex_q": 1,
      "hex_r": 1,
      "hex_s": 1,
      "skill_tree_id": 3,
      "allow_verbal_feedback": false,
      "allow_quantitative_feedback": true,
      "image_address": "https://www.knowol.com/wp-content/uploads/2017/02/abraham-lincoln-1863.jpg",
      "title": "ok",
      "hex_string": "1,1,1"
    },
    {
      "hex_id": 2,
      "note_id": 1,
      "hex_q": 2,
      "hex_r": 2,
      "hex_s": 2,
      "skill_tree_id": 3,
      "allow_verbal_feedback": true,
      "allow_quantitative_feedback": false,
      "image_address": "https://thecolloquial.com/wp-content/uploads/2020/07/Thomas_Paine_rev1-e1593883311631-319x180.jpg",
      "title": "asdf",
      "hex_string": "2,2,2"
    }
  ],
  "hex_string_list": [["1,1,1"], ["2,2,2"]],
  "name": "test tree",
  "theme": "yagami"
}
```

## Helpful Links Section

## [Stack Overflow link that helped me](https://stackoverflow.com/questions/65540356/creating-a-nested-json-from-a-value-in-django-rest-framework)

## [Django REST Framework documentation on serializers](https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield)