10

我的 django 应用程序中有一个JSONField。数据可能如下所示:

{
"05/2013" : 101,
"04/2013" : 100.9,
"03/2013" : 100.5,
"02/2013" : 100.3,
"01/2013" : 100.3
}

这是一个价格指数。当我从字段中获取数据时,我想保留插入数据的顺序。

我查看了使用OrderedDict. Dict(我猜)使用词法排序,因此输出会以这种格式丢失它的原始顺序。我尝试将日期翻转为 format 2012-012012-02依此类推,但输出仍然乱码。部分输出:

"2011-08":104.2,
  "2011-09":104,
  "2011-02":102.3,
  "2011-03":102.5,
  "2011-01":102,
  "2011-06":104,
  "2011-07":103.7,
  "2011-04":103.1,
  "2011-05":103.6,
  "2013-04":100.9,
  "2013-05":101,
  "2012-10":106,
  "2012-11":105.5,

我不确定这是哪种类型,我在寻找解决方案方面落后了一步。欣赏任何想法。

编辑: 这是模型字段声明

from jsonfield import JSONField
...
values = JSONField(null=True, blank=True, verbose_name=_("values"),load_kwargs={'object_pairs_hook': collections.OrderedDict})
...
4

2 回答 2

11

如果您需要在 JSONFIeld 中维护键顺序,您可以覆盖原生 JSONField 的 db_type 以使用 json 而不是 jsonb:

class RawJSONField(JSONField):

    def db_type(self, connection):
        return 'json'

Postgres 文档中:

主要的实际区别是效率之一。json 数据类型存储输入文本的精确副本,处理函数必须在每次执行时重新解析;而 jsonb 数据以分解的二进制格式存储,由于增加了转换开销,因此输入速度稍慢,但处理速度明显加快,因为不需要重新解析。jsonb 还支持索引,这是一个显着的优势。

如果您不需要根据 JSON blob 的内容对数据进行索引,并且确实需要维护实例化字典时创建的键顺序(也许您正在使用对 JSON 键进行假设的客户端库订单),那么这可能对你有用。

于 2019-09-15T06:08:51.073 回答
1

这是一个有趣的问题,特别是因为无法保证 javascript 对象、JSON 本身或 python dict 中的字段顺序

考虑到上述情况,如果我们将在数据库 + 序列化 + 反序列化 + 表示的某种组合中正确设置订单,它将仅适用于这种(相当狭窄的)配置

例如 django-jsonfield 将 JSON 序列化(默认情况下)到文本字段,因此在数据库级别它可能是安全的,但是从少数 json 模块(json、simplejson、ujson、yajl)反序列化到字典然后所有顺序都丢失了

django 1.9 引入了本机 postgresql JSONField - 这里甚至在数据库级别上也没有保证,因为数据在内部存储为 jsonb - 二进制优化 JSON

OrderedDict在我看来,如果顺序很重要,最好更改数据的存储方式,而不是搜索序列化- 让我们将数据存储在表中:

[{date: "05/2013", price: 101},
 {date: "04/2013", price: 100.9},
 {date: "03/2013", price: 100.5},
 {date: "02/2013", price: 100.3},
 {date: "01/2013", price: 100.3}]

我们有顺序保证,数据可以线性处理,我们不依赖于特殊的实现。

于 2016-06-13T23:25:44.977 回答