You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django连接MongoDB查询报错:JSON对象需为str/bytes而非OrderedDict

解决Django+MongoDB获取数据时的TypeError:JSON对象需为str/bytes而非OrderedDict

问题场景

使用Django配合Djongo连接MongoDB获取员工数据时,持续报错:

Exception Type: TypeError at /api/employes/
Exception Value: the JSON object must be str, bytes or bytearray, not OrderedDict

相关环境与代码

员工集合数据格式

{
  "_id": {
    "$oid": "511d0a9f181b16509ae5f7dd"
  },
  "nom": "Leberre",
  "prenom": "Stephanie",
  "anciennete": 1,
  "adresse": {
    "numero": 79,
    "codepostal": 9500,
    "ville": "Toulouse",
    "rue": "Jean Moulin"
  },
  "tel": 559608352,
  "prime": 1500
}

models.py

from django.db import models

class Employee(models.Model):
    nom = models.CharField(max_length=100)
    prenom = models.CharField(max_length=100)
    anciennete = models.IntegerField()
    adresse = models.JSONField()
    tel = models.CharField(max_length=20, blank=True, null=True)
    prime = models.IntegerField(blank=True, null=True)

    def __str__(self):
        return f"{self.nom}, {self.prenom}"

serializers.py

from rest_framework import serializers
from .models import Employee

class EmployeeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Employee
        fields = '__all__'

views.py

from rest_framework.response import Response
from rest_framework import generics
from .models import Employee
from .serializers import EmployeeSerializer

class EmployeeListView(generics.ListAPIView):
    queryset = Employee.objects.all()
    serializer_class = EmployeeSerializer

    def list(self, request, *args, **kwargs):
        serializer = self.get_serializer(self.get_queryset(), many=True)
        return Response(serializer.data)

settings.py数据库配置

DATABASES = {
    'default': {
        'ENGINE': 'djongo',
        'NAME': 'employes',
    }
}

解决方法

方案1:自定义JSON字段处理OrderedDict转换

修改models.py,替换默认的JSONField为自定义字段,确保从MongoDB读取的OrderedDict能转为可序列化的字典:

from django.db import models
from django.core.serializers.json import DjangoJSONEncoder
from collections import OrderedDict

class MongoJSONField(models.JSONField):
    def from_db_value(self, value, expression, connection):
        if isinstance(value, OrderedDict):
            return dict(value)
        return super().from_db_value(value, expression, connection)

class Employee(models.Model):
    nom = models.CharField(max_length=100)
    prenom = models.CharField(max_length=100)
    anciennete = models.IntegerField()
    adresse = MongoJSONField(encoder=DjangoJSONEncoder)
    tel = models.CharField(max_length=20, blank=True, null=True)
    prime = models.IntegerField(blank=True, null=True)

    def __str__(self):
        return f"{self.nom}, {self.prenom}"

方案2:在序列化器中显式处理adresse字段

修改serializers.py,对adresse字段添加自定义序列化方法,将OrderedDict转为普通字典:

from rest_framework import serializers
from .models import Employee
from collections import OrderedDict

class EmployeeSerializer(serializers.ModelSerializer):
    adresse = serializers.SerializerMethodField()

    class Meta:
        model = Employee
        fields = '__all__'

    def get_adresse(self, obj):
        if isinstance(obj.adresse, OrderedDict):
            return dict(obj.adresse)
        return obj.adresse

方案3:调整Djongo配置强制返回普通字典

修改settings.py的数据库配置,添加OPTIONS让Djongo使用普通字典而非OrderedDict:

DATABASES = {
    'default': {
        'ENGINE': 'djongo',
        'NAME': 'employes',
        'OPTIONS': {
            'use_legacy_json': False,
            'json_options': {
                'object_pairs_hook': dict
            }
        }
    }
}

验证方法

修改完成后,重启Django服务,访问/api/employes/接口,确认数据能正常返回,无TypeError报错。

内容的提问来源于stack exchange,提问作者G.M.T.K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 18:05:54