Postgres 9.4'te bir JSON dizi öğesiyle json_to_record kullanılırken “HATA: hatalı biçimlendirilmiş dizi değişmez değeri”


9

Bu sorunu güzel bir şekilde göstermektedir:

B sütunu bir dizi değil, metin türündeyse aşağıdakiler çalışır:

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

bSütunu bir dizi olarak tanımlarsam, bu hatayı alıyorum:

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.

Bir JSON dizisini hedef sütun türünün Postgres dizisine dönüştürmeye nasıl ikna edebilir / zorlayabilirim json_to_record(veya json_populate_record)?

Yanıtlar:


6

Chris'in cevabında sadece küçük bir değişiklik var:

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

Fikir aynı: JSON dizisini bir diziye masaj yapın - bu durumda, bir dizi değişmeziyle. Biraz temiz görünümlü koda ek olarak (onu seviyorum, regex genellikle bu konuda çok yardımcı olmaz :), çok da hızlı görünüyor:

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

Bu veri kümesinde ve test kutumda, normal ifade sürümü ve ortalama 300 ms yürütme süresi gösterilirken, sürümüm 210 ms gösterir .


1

Bu en zarif çözüm olmayabilir, ancak sorunlarınızı düzeltir ...

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

Nasıl çalıştığı oldukça basit:

İlk olarak , textdizeyi alın bve yararlı bilgilere indirin. Bu kullanılarak yapılır regexp_replace()olarak

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

tüm örneklerini kaldırmak için [, ", ]ve herhangi bir boşluk karakterleri, ya da daha spesifik olarak, bu karakterlerden herhangi örneklerini değiştirmek için ''ve bayrak kullanarak bu küresel, sinyal uygulamak 'g'.

Ardından , dizeyi string_to_array()as kullanarak bir diziye ayırın

string_to_array(your_string,',')

burada bu durumda your_stringbasitçe yukarıdakilerin sonucudur regexp_replace(). İkinci argüman , öğelerin virgülle ayrıldığını ','belirtir string_to_array().

Bu, text[]istediğiniz girişleri içeren bir alan sağlar.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.