tru*_*one 7 django django-jsonfield jsonencoder jsondecoder
我很难保留存储在 Django JSONField 中的 JSON 对象中的键顺序。我已尝试按照文档使用自定义编码器和解码器,但 JSON 对象不断重新排序自身:
>>>from models import MyModel
>>>my_dict = {"c": 3, "b": 2, "a": 1}
>>>my_model = MyModel()
>>>my_model.my_field = my_dict
>>>my_model.save()
>>>my_model.refresh_from_db()
>>>my_model.my_field
OrderedDict([('a',1), ('b', 2), ('c', 3)])
Run Code Online (Sandbox Code Playgroud)
我原以为它会回来OrderedDict([('c',3), ('b', 2), ('a', 1)])。
这是我到目前为止所尝试过的:
模型.py:
import collections
import json
from django.db import models
class OrderedEncoder(json.JSONEncoder):
def encode(self, o):
if isinstance(o, collections.OrderedDict):
encoded_objs = [
f"{self.encode(k)}: {self.encode(v)}"
for k, v in o.items()
]
return f"{{{','.join(encoded_objs)}}}"
else:
return super().encode(o)
class OrderedDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
default_kwargs = {
"object_pairs_hook": collections.OrderedDict
}
default_kwargs.update(kwargs)
super().__init__(*args, **default_kwargs)
class MyModel(models.Model):
my_field = models.JSONField(encoder=OrderedEncoder, decoder=OrderedDecoder)
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
小智 1
遇到了同样的问题,我确实设法解决了它。不确定这是否是最好的方法,但它解决了我的问题,即键值的顺序不同。
模型.py:
import collections
import json
class myModel(models.Model):
_field_to_contain_ordered_dict = models.TextField(
null=False,
blank=False,
)
@property
def my_ordereddict_field(self):
decoder = json.JSONDecoder(object_pairs_hook=collections.OrderedDict)
# Below is a small hack to ensure the string is formatted as json
# can be very peculiar with ' and "
json_data = json.dumps(ast.literal_eval(self._field_to_contain_ordered_dict))
response_ordereddict = decoder.decode(json_data)
return response_ordereddict
@my_ordereddict_field.setter
def my_ordereddict_field(self, value):
self._field_to_contain_ordered_dict = value
Run Code Online (Sandbox Code Playgroud)
然后在我访问的代码中myModel.my_ordereddict_field我得到了正确的项目序列。
在代码中初始化
my_model = myModel.objects.create(
my_ordereddict_field={
"Last Name": "Stark",
"First Name": "Arija",
"Level1": "my level 1",
"Level2": "my level 2",
"Level3": "my level 3",
"Level4": "my level 4",
}
)
my_model.refresh_from_db()
Run Code Online (Sandbox Code Playgroud)
然后,如果您检查 type(my_model.my_ordereddict_field) 您有 OrderedDict 并且序列是正确的
| 归档时间: |
|
| 查看次数: |
1411 次 |
| 最近记录: |