“ ข้อผิดพลาด: ตัวอักษรของอาเรย์ที่ผิดรูปแบบ” เมื่อใช้ json_to_record กับอิลิเมนต์อาร์เรย์ JSON ใน Postgres 9.4


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.

ฉันจะโน้มน้าว / coerce json_to_record(หรือjson_populate_record) เพื่อแปลงอาร์เรย์ JSON เป็นอาร์เรย์ Postgres ของประเภทคอลัมน์เป้าหมายได้อย่างไร

คำตอบ:


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 ลงในอาเรย์ - ในกรณีนี้ผ่านตัวอักษรของอาเรย์ นอกจากโค้ดที่ดูสะอาดตากว่าเล็กน้อย (แม้ว่าฉันชอบมัน regex มักจะไม่ช่วยอะไรมากในเรื่องนี้ :) ดูเหมือนว่าจะเร็วขึ้นเล็กน้อยด้วย:

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

บนชุดนี้และบนกล่องการทดสอบของฉันแสดงรุ่น regex และการดำเนินการเวลาเฉลี่ยของ300 มิลลิวินาทีในขณะที่รุ่นแสดงของฉัน210 มิลลิวินาที


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()เป็น

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

จะลบทุกกรณีของ[, ", ]และตัวอักษรช่องว่างใด ๆ หรือมากขึ้นโดยเฉพาะเพื่อทดแทนกรณีของตัวละครเหล่านี้กับใด ๆและเพื่อใช้นี้ทั่วโลกส่งสัญญาณโดยใช้ธง'''g'

ถัดไปเพียงแค่แยกสตริงเพื่ออาร์เรย์ใช้string_to_array()เป็น

string_to_array(your_string,',')

ซึ่งในกรณีนี้เป็นเพียงผลจากการดังกล่าวข้างต้นyour_string regexp_replace()อาร์กิวเมนต์ที่สอง','ระบุstring_to_array()ว่ารายการนั้นคั่นด้วยเครื่องหมายจุลภาค

นี่จะให้text[]ฟิลด์ที่มีรายการที่คุณต้องการ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.