Postgres 9.4에서 JSON 배열 요소와 함께 json_to_record를 사용할 때“오류 : 잘못된 배열 리터럴”


9

이것은 문제를 잘 보여줍니다.

열 b가 텍스트 유형이고 배열이 아닌 경우 다음이 작동합니다.

select * 
from json_to_record('{"a":1,"b":["hello", "There"],"c":"bar"}') 
    as x(a int, b text, d text);

 a |         b          | d
---+--------------------+---
 1 | ["hello", "There"] |

그러나 b열을 배열로 정의하면 이 오류가 발생합니다.

select * 
from json_to_record('{"a":1,"b":["hello", "There"],"c":"bar"}') 
    as x(a int, b text[], d text)

ERROR:  malformed array literal: "["hello", "There"]"
DETAIL:  "[" must introduce explicitly-specified array dimensions.

JSON 배열을 대상 열 유형의 Postgres 배열로 변환 하도록 설득 / 강압 json_to_record(또는 json_populate_record)하려면 어떻게해야합니까?

답변:


6

Chris의 대답에 약간의 변형이 있습니다.

SELECT a, translate(b, '[]', '{}')::text[] AS b, d
FROM json_to_record('{"a": 1, "b": ["hello", "There"], "c": "bar"}')
AS x(a int, b text, d text);

아이디어는 동일합니다.이 경우 배열 리터럴을 통해 JSON 배열을 배열로 마사지하십시오. 조금 더 깔끔하게 보이는 코드 외에도 (정말 좋아하는 정규 표현식은 일반적 으로이 점에서별로 도움이되지 않습니다.)

CREATE TABLE jsonb_test (
    id serial,
    data jsonb
);

INSERT INTO jsonb_test (id, data)
SELECT i, format('{"a": %s, "b": ["foo", "bar"], "c": "baz"}', i::text)::jsonb 
FROM generate_series(1,10000) t(i);

SELECT a, string_to_array(regexp_replace(b, '\[*\"*\s*\]*','','g'),',') AS b, d
FROM jsonb_test AS j, 
LATERAL json_to_record(j.data::json) AS r(a int, b text, d text);

-- versus 

SELECT a, translate(b, '[]', '{}')::text[] AS b, d
FROM jsonb_test AS j, 
LATERAL json_to_record(j.data::json) AS r(a int, b text, d text);

이 데이터 세트와 내 테스트 상자에서 정규식 버전과 평균 실행 시간은 300ms 이고 내 버전은 210ms 입니다.


1

이것은 가장 우아한 해결책은 아니지만 문제를 해결할 것입니다 ...

SELECT a,string_to_array(regexp_replace(b, '\[*\"*\s*\]*','','g'),',') AS b,d
FROM json_to_record('{"a":1,"b":["hello", "There"],"c":"bar"}')
AS x(a int, b text, d text);

작동 방식은 매우 간단합니다.

먼저 에서 text문자열을 가져와 b유용한 정보로 분리하십시오. 이것은 regexp_replace()as 를 사용하여 수행 됩니다.

regexp_replace(b, '\[*\"*\s*\]*','','g')

의 모든 인스턴스를 제거하기 위해 [, ", ], 및 공백 문자, 또는 더 구체적으로, 이러한 문자의 인스턴스를 대체 ''하고 플래그를 사용하여이 세계적으로 신호 적용 'g'.

다음 으로 간단히 string_to_array()as를 사용하여 문자열을 배열로 분할하십시오.

string_to_array(your_string,',')

이 경우 your_string단순히 위의 결과입니다 regexp_replace(). 두 번째 인수 ','string_to_array()항목이 쉼표로 구분되어 있음을 나타냅니다 .

text[]원하는 항목이 포함 된 필드 가 생성됩니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.