L ERI ERROR: không đúng định dạng mảng chữ khi sử dụng json_to_record với phần tử mảng JSON trong Postgres 9.4


9

Điều này minh họa vấn đề độc đáo:

Khi cột b có kiểu văn bản và không phải là một mảng, các công việc sau:

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"] |

Nhưng nếu tôi xác định bcột là một mảng, tôi sẽ gặp lỗi này:

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.

Làm cách nào tôi có thể thuyết phục / ép buộc json_to_record(hoặc json_populate_record) chuyển đổi một mảng JSON thành mảng Postgres của loại cột mục tiêu?

Câu trả lời:


6

Chỉ là một biến thể nhỏ cho câu trả lời của 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);

Ý tưởng là như nhau: xoa bóp mảng JSON thành một mảng - trong trường hợp này, thông qua một mảng bằng chữ. Ngoài mã trông gọn gàng hơn một chút (mặc dù tôi yêu nó, regex thường không giúp được gì nhiều trong vấn đề này :), nó dường như cũng nhanh hơn một chút:

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);

Trên tập dữ liệu này và trên hộp thử nghiệm của tôi, phiên bản regex hiển thị và thời gian thực hiện trung bình là 300 ms , trong khi phiên bản của tôi hiển thị 210 ms .


1

Đây có thể không phải là giải pháp tao nhã nhất, nhưng nó sẽ khắc phục vấn đề của bạn ...

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);

Nó khá đơn giản về cách thức hoạt động:

Đầu tiên , lấy textchuỗi trong bvà tước nó xuống thông tin hữu ích. Điều này được thực hiện bằng cách sử dụng regexp_replace()như

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

để loại bỏ tất cả các trường hợp [, ", ], và bất kỳ ký tự khoảng trắng, hay cụ thể hơn, để thay thế bất kỳ trường hợp của những nhân vật này với '', và để áp dụng điều này trên toàn cầu, hiệu bằng cờ 'g'.

Tiếp theo , chỉ cần chia chuỗi thành một mảng bằng cách sử dụng string_to_array()như

string_to_array(your_string,',')

trong trường hợp your_stringnày chỉ đơn giản là kết quả của những điều trên regexp_replace(). Đối số thứ hai ','chỉ ra string_to_array()rằng các mục được phân tách bằng dấu phẩy.

Điều này sẽ mang lại một text[]trường có chứa các mục mong muốn của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.