创建 JSON 对象时,数字的显示方式会有所不同

Display of numbers varies when creating a JSON object

提问人:Thomas 提问时间:3/10/2023 最后编辑:Erwin BrandstetterThomas 更新时间:3/12/2023 访问量:55

问:

我有以下功能:

CREATE OR REPLACE FUNCTION aggregate_view(ticker text, from_time timestamp)
RETURNS TABLE (data text)
LANGUAGE sql AS
$func$
SELECT
    json_build_object(
        'candles',
        (SELECT json_agg(array [EXTRACT(EPOCH FROM ts_bucket), "open", high, low, "close", volume :: BIGINT]) AS json_array_of_arrays
        FROM exchange.candles_d1
        WHERE exchange.candles_d1.ticker = $1 AND candles_d1.ts_bucket >= $2 AND candles_d1.ts_bucket < $2 + INTERVAL '1 hour'),

        'kvwap',
        (SELECT json_agg(array [EXTRACT(EPOCH FROM ts_bucket), m1, m5, m15, m30, h1, h2, h4, d1, low, vwap, high]) AS json_array_of_arrays
        FROM exchange.kvwap_d1
        WHERE exchange.kvwap_d1.ticker = $1 AND kvwap_d1.ts_bucket >= $2 AND kvwap_d1.ts_bucket < $2 + INTERVAL '1 hour'),

        'zones',
        (SELECT json_agg(array[EXTRACT(EPOCH FROM ts_confirmation)::BIGINT, EXTRACT(EPOCH FROM ts_end)::BIGINT, confirmations, CAST(is_continuation AS INT)])
        AS json_array_of_array
        FROM analysis.zones
        WHERE analysis.zones.ticker = $1 AND "interval" = 'D1' AND ts_confirmation >= $2 AND ts_confirmation < $2+ INTERVAL '1 hour')
    )
$func$;

时间戳存储为 (time - EPOCH),但在输出 json 中,格式因表而异。每个块中的第一个值是时间戳:

 {
   "candles":[
      [
         1577836800,
         7189.43,
         7260.43,
         7170.15,
         7197.57,
         409678761
      ]
   ],
   "kvwap":[
      [
         1.5778368e+09,
         7213.8125,
         7213.5947,
         7212.4907,
         7210.914,
         7209.1133,
         7207.789,
         7207.2,
         7206.961,
         7170.15,
         7213.8574,
         7260.43
      ]
   ],
   "zones":null
}

请注意,一个时间戳写成 1577836800,而另一个写成 1.5778368e+09,这是相同的数字。

为什么?以及如何防止数字以科学记数法显示?

SQL 数组 JSON PostgreSQL 浮点

评论

1赞 Erwin Brandstetter 3/10/2023
对于任何此类问题,披露您的 Postgres 版本应该是显而易见的。另外,请从与 E 符号与普通符号问题无关的问题中去除所有噪音。将可重现的示例简化为两个数组,每个数组包含两个元素,并公开输入数据类型。

答:

1赞 Erwin Brandstetter 3/10/2023 #1

Postgres 数组存储一种数据类型的元素。如果输入类型不同,ARRAY 构造函数会找到最佳公分母(如果可能)。

最有可能的是,表中的一列 () 的数据类型为 real()。(没有一个是。这将强制构造数组的数据类型为 。默认情况下,as 数字的表示形式为科学记数法:。演员阵容保留了这一点。瞧。m1, m5, m15, m30, h1, h2, h4, d1, low, vwap, highexchange.kvwap_d1float4float8real[]1577836800real1.5778368e+09json

在将所有浮点输入填充到数组中之前将其转换为。numeric

或者用 代替 . 将数值数据强制转换为类型,以便在内部存储它们。手册:jsonbjsonjsonbnumeric

一个值得注意的语义上无关紧要的细节是,在 中,数字将根据基础类型的行为进行打印。在实践中,这意味着用 E 符号输入的数字将在没有它的情况下打印......jsonbnumeric