如何将json数组转换为文本数组?

时间:2017-07-21 17:11:09

标签: arrays json postgresql

此解决方法不起作用

CREATE FUNCTION json_array_castext(json) RETURNS text[] AS $f$
  SELECT array_agg(x::text) FROM json_array_elements($1) t(x);
$f$ LANGUAGE sql IMMUTABLE;

-- Problem:
SELECT 'hello'='hello';  -- true...
SELECT  (json_array_castext('["hello","world"]'))[1] = 'hello'; -- false!

那么,如何获得真正的文本数组?

PS:与所谓的“一等公民”JSONb,同样的问题。

编辑:@OtoShavadze之后的好答案(评论已解决!),PostgreSQL开发人员的清单为什么x::text不是演员?(使用第9.5.6页)以及为什么它不会产生警告或错误?

5 个答案:

答案 0 :(得分:4)

尝试json_array_elements_text 而不是json_array_elements,并且您不需要显式转换为文字(x::text),因此您可以使用:

CREATE or replace FUNCTION json_array_castext(json) RETURNS text[] AS $f$
    SELECT array_agg(x) FROM json_array_elements_text($1) t(x);
$f$ LANGUAGE sql IMMUTABLE;

有关您的其他问题

  

为什么x :: text不是演员?

这是强制转换,因此,它没有给出任何错误,但是当将json字符串转换为这样的文本:::text时,postgres会为值添加引号。

仅出于测试目的,我们可以将您的功能再次更改为原始版本(正如您的问题所示)并尝试:

SELECT  
(json_array_castext('["hello","world"]'))[1] = 'hello',
(json_array_castext('["hello","world"]'))[1],
'hello'

如您所见,(json_array_castext('["hello","world"]'))[1]提供了"hello"而不是hello。这就是为什么在比较这些值时得到false的原因。

答案 1 :(得分:1)

对于PostgreSQL的这种丑陋行为,有一个丑陋的强制转换方法,即运算符#>>'{}'

CREATE or replace FUNCTION json_array_castext(json) RETURNS text[] AS $f$
    SELECT array_agg(x#>>'{}') FROM json_array_elements($1) t(x);
$f$ LANGUAGE sql IMMUTABLE;

SELECT  (json_array_castext('["hello","world"]'))[1] = 'hello'; -- true!

答案 2 :(得分:1)

奥托的answer是一个救星,但确实有一个边界案例让我绞尽脑汁。由于演员阵容的有损性质,除了你有一个空json数组的情况外,它的工作原理很完美。在这种情况下,你会期望返回一个空数组,但它实际上什么都不返回。作为一种解决方法,如果你只是将返回值与一个空数组连接起来,那么在实际有返回的情况下它将没有任何影响,但是当你有一个空数组时做正确的事情。以下是实现解决方法的更新SQL函数(适用于jsonjsonb)。

CREATE or replace FUNCTION json_array_casttext(json) RETURNS text[] AS $f$
    SELECT array_agg(x) || ARRAY[]::text[] FROM json_array_elements_text($1) t(x);
$f$ LANGUAGE sql IMMUTABLE;

CREATE or replace FUNCTION jsonb_array_casttext(jsonb) RETURNS text[] AS $f$
    SELECT array_agg(x) || ARRAY[]::text[] FROM jsonb_array_elements_text($1) t(x);
$f$ LANGUAGE sql IMMUTABLE;

像这样的一些特点指出了将文档数据库集成到成熟的关系数据库中的粗略边缘,但Postgres在处理大多数文档数据库方面做了令人钦佩的工作。

答案 3 :(得分:1)

{
"scope": "acabado"

测试用例:

  • CREATE or replace FUNCTION json_to_array(json) RETURNS text[] AS $f$ SELECT coalesce(array_agg(x), CASE WHEN $1 is null THEN null ELSE ARRAY[]::text[] END) FROM json_array_elements_text($1) t(x); $f$ LANGUAGE sql IMMUTABLE; =>一个元素数组
  • select json_to_array('["abc"]') =>一个空数组
  • select json_to_array('[]') =>空

答案 4 :(得分:0)

对于我来说,这有助于使结果反映3种状态,即空,空文本数组和非空文本数组(取决于输入)。希望这对某人有用。

CREATE OR REPLACE FUNCTION json_array_text_array(JSON)
  RETURNS TEXT [] AS $$
DECLARE
  result TEXT [];
BEGIN
  IF $1 ISNULL
  THEN
    result := NULL;
  ELSEIF json_array_length($1) = 0
    THEN
      result := ARRAY [] :: TEXT [];
  ELSE
    SELECT array_agg(x) FROM json_array_elements_text($1) t(x) INTO result;
  END IF;
  RETURN result;
END;
$$
LANGUAGE plpgsql
IMMUTABLE
STRICT;