これは問題をうまく説明しています:
列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_to_record
(またはjson_populate_record
)JSON配列をターゲット列タイプのPostgres配列に変換するには?
クリスの答えのほんの少しのバリエーション:
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);
このデータセットと私のテストボックスでは、正規表現バージョンは0 msの平均実行時間を示していますが、私のバージョンは210 msを示しています。
これは最もエレガントなソリューションではないかもしれませんが、問題を解決します...
_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);
_
それがどのように機能するかは非常に簡単です:
First、text
のb
文字列を取得し、有用な情報まで削除します。これはregexp_replace()
を使用して行われます
_regexp_replace(b, '\[*\"*\s*\]*','','g')
_
_[
_、_"
_、_]
_、および空白文字のすべてのインスタンスを削除する、またはより具体的には、これらの文字のインスタンスを_''
_に置き換えて適用するこれはグローバルにフラグ_'g'
_を使用して通知されます。
Next、string_to_array()
を使用して文字列を配列に分割するだけ
_string_to_array(your_string,',')
_
この場合、_your_string
_は上記のregexp_replace()
の結果です。 2番目の引数_','
_は、項目がカンマ区切りであることをstring_to_array()
に示しました。
これにより、目的のエントリを含む_text[]
_フィールドが生成されます。