Repository: netbox-community/netbox

Issue:
Add missing Serializer annotations
### NetBox version

v3.3.1

### Python version

3.10

### Steps to Reproduce

1. Download swagger.json
2. GET request on /api/ipam/vlan-groups/{ID} on vlan groups with sope

### Expected Behavior

API documentation and returned object use same types.

### Observed Behavior

Swagger.json list field sope as type string, field in returned object is JSON


Discussion:
Proposed fix: Add missing serailizer annotations. The diff adds them to all objects I could identify where the type returned is not string. Only VlanGoup.scope is currently displayed in swagger.json.
```
diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py
index 533238d36..764c7750a 100644
--- a/netbox/extras/api/serializers.py
+++ b/netbox/extras/api/serializers.py
@@ -403,6 +403,7 @@ class ScriptSerializer(serializers.Serializer):
     vars = serializers.SerializerMethodField(read_only=True)
     result = NestedJobResultSerializer()
 
+    @swagger_serializer_method(serializer_or_field=serializers.JSONField)
     def get_vars(self, instance):
         return {
             k: v.__class__.__name__ for k, v in instance._get_vars().items()
diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py
index 6244e5f04..fa8b563e9 100644
--- a/netbox/ipam/api/serializers.py
+++ b/netbox/ipam/api/serializers.py
@@ -190,6 +190,7 @@ class VLANGroupSerializer(NetBoxModelSerializer):
         ]
         validators = []
 
+    @swagger_serializer_method(serializer_or_field=serializers.JSONField)
     def get_scope(self, obj):
         if obj.scope_id is None:
             return None
diff --git a/netbox/users/api/nested_serializers.py b/netbox/users/api/nested_serializers.py
index e9e730cc4..0d8f7ae42 100644
--- a/netbox/users/api/nested_serializers.py
+++ b/netbox/users/api/nested_serializers.py
@@ -1,5 +1,6 @@
 from django.contrib.auth.models import Group, User
 from django.contrib.contenttypes.models import ContentType
+from drf_yasg.utils import swagger_serializer_method
 from rest_framework import serializers
 
 from netbox.api.fields import ContentTypeField
@@ -56,8 +57,10 @@ class NestedObjectPermissionSerializer(WritableNestedSerializer):
         model = ObjectPermission
         fields = ['id', 'url', 'display', 'name', 'enabled', 'object_types', 'groups', 'users', 'actions']
 
+    @swagger_serializer_method(serializer_or_field=serializers.ListField)
     def get_groups(self, obj):
         return [g.name for g in obj.groups.all()]
 
+    @swagger_serializer_method(serializer_or_field=serializers.ListField)
     def get_users(self, obj):
         return [u.username for u in obj.users.all()]
```

swagger.json diff:
```
*** swagger.orig.json   2022-08-31 20:51:08.293884289 +0200
--- swagger.new.json    2022-08-31 20:50:10.702636759 +0200
***************
*** 13184,13192 ****
                  },
                "scope" : { 
                    "readOnly" : true,
                    "title" : "Scope",
!                   "type" : "string"
                  },
                "scope_id" : { 
                    "title" : "Scope id",
                    "type" : "integer",
--- 13184,13192 ----
                  },
                "scope" : { 
                    "readOnly" : true,
                    "title" : "Scope",
!                   "type" : "object"
                  },
                "scope_id" : { 
                    "title" : "Scope id",
                    "type" : "integer",
```

Resolving patch:
diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py
--- a/netbox/extras/api/serializers.py
+++ b/netbox/extras/api/serializers.py
@@ -403,6 +403,7 @@ class ScriptSerializer(serializers.Serializer):
     vars = serializers.SerializerMethodField(read_only=True)
     result = NestedJobResultSerializer()
 
+    @swagger_serializer_method(serializer_or_field=serializers.JSONField)
     def get_vars(self, instance):
         return {
             k: v.__class__.__name__ for k, v in instance._get_vars().items()
diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py
--- a/netbox/ipam/api/serializers.py
+++ b/netbox/ipam/api/serializers.py
@@ -190,6 +190,7 @@ class Meta:
         ]
         validators = []
 
+    @swagger_serializer_method(serializer_or_field=serializers.JSONField)
     def get_scope(self, obj):
         if obj.scope_id is None:
             return None
diff --git a/netbox/users/api/nested_serializers.py b/netbox/users/api/nested_serializers.py
--- a/netbox/users/api/nested_serializers.py
+++ b/netbox/users/api/nested_serializers.py
@@ -1,5 +1,6 @@
 from django.contrib.auth.models import Group, User
 from django.contrib.contenttypes.models import ContentType
+from drf_yasg.utils import swagger_serializer_method
 from rest_framework import serializers
 
 from netbox.api.fields import ContentTypeField
@@ -56,8 +57,10 @@ class Meta:
         model = ObjectPermission
         fields = ['id', 'url', 'display', 'name', 'enabled', 'object_types', 'groups', 'users', 'actions']
 
+    @swagger_serializer_method(serializer_or_field=serializers.ListField)
     def get_groups(self, obj):
         return [g.name for g in obj.groups.all()]
 
+    @swagger_serializer_method(serializer_or_field=serializers.ListField)
     def get_users(self, obj):
         return [u.username for u in obj.users.all()]


Test patch: