Güncelleme : PostgreSQL 9.5 ile , jsonb
PostgreSQL'in içinde bazı manipülasyon işlevleri vardır (ancak değerlerin json
manipüle edilmesi için dökümler gerekmez json
).
2 (veya daha fazla) JSON nesnesini (veya sıralı dizileri) birleştirme:
SELECT jsonb '{"a":1}' || jsonb '{"b":2}', -- will yield jsonb '{"a":1,"b":2}'
jsonb '["a",1]' || jsonb '["b",2]' -- will yield jsonb '["a",1,"b",2]'
Böylece, basit bir anahtar ayarlamak aşağıdakileri kullanarak yapılabilir:
SELECT jsonb '{"a":1}' || jsonb_build_object('<key>', '<value>')
Nerede <key>
dize olmalı ve <value>
tür ne olursa olsun to_jsonb()
kabul edilebilir.
İçin bir JSON hiyerarşisinde bir değer derine ayarlayarak , jsonb_set()
fonksiyon kullanılabilir:
SELECT jsonb_set('{"a":[null,{"b":[]}]}', '{a,1,b,0}', jsonb '{"c":3}')
-- will yield jsonb '{"a":[null,{"b":[{"c":3}]}]}'
Aşağıdakilerin tam parametre listesi jsonb_set()
:
jsonb_set(target jsonb,
path text[],
new_value jsonb,
create_missing boolean default true)
path
JSON dizi dizinleri de içerebilir ve orada görünen negatif tamsayılar JSON dizilerinin sonundan itibaren sayılabilir. Ancak, var olmayan ancak pozitif bir JSON dizi dizini, öğeyi dizinin sonuna ekler:
SELECT jsonb_set('{"a":[null,{"b":[1,2]}]}', '{a,1,b,1000}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}'
İçin (orijinal tüm değerleri korunurken) JSON diziye sokulması , jsonb_insert()
fonksiyon kullanılabilir ( 9.6+ olarak, bu fonksiyon, sadece bu bölümde ):
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2')
-- will yield jsonb '{"a":[null,{"b":[2,1]}]}', and
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b,0}', jsonb '2', true)
-- will yield jsonb '{"a":[null,{"b":[1,2]}]}'
Aşağıdakilerin tam parametre listesi jsonb_insert()
:
jsonb_insert(target jsonb,
path text[],
new_value jsonb,
insert_after boolean default false)
Yine, path
JSON dizilerinin sonundan itibaren sayılan negatif tamsayılar .
Yani, f.ex. bir JSON dizisinin sonuna ekleme aşağıdakilerle yapılabilir:
SELECT jsonb_insert('{"a":[null,{"b":[1,2]}]}', '{a,1,b,-1}', jsonb '3', true)
-- will yield jsonb '{"a":[null,{"b":[1,2,3]}]}', and
Bununla birlikte, bu fonksiyon biraz farklı (daha çalışmaktadır jsonb_set()
) zaman path
içinde target
bir JSON nesnenin anahtarıdır. Bu durumda, yalnızca anahtar kullanılmadığında yalnızca JSON nesnesi için yeni bir anahtar / değer çifti ekleyecektir. Kullanılırsa bir hata oluşturur:
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,c}', jsonb '[2]')
-- will yield jsonb '{"a":[null,{"b":[1],"c":[2]}]}', but
SELECT jsonb_insert('{"a":[null,{"b":[1]}]}', '{a,1,b}', jsonb '[2]')
-- will raise SQLSTATE 22023 (invalid_parameter_value): cannot replace existing key
JSON nesnesinden (veya bir diziden) bir anahtarı (veya dizini) silmek-
operatörle yapılabilir :
SELECT jsonb '{"a":1,"b":2}' - 'a', -- will yield jsonb '{"b":2}'
jsonb '["a",1,"b",2]' - 1 -- will yield jsonb '["a","b",2]'
JSON hiyerarşisinin derinliklerinden silme#-
operatörle yapılabilir :
SELECT '{"a":[null,{"b":[3.14]}]}' #- '{a,1,b,0}'
-- will yield jsonb '{"a":[null,{"b":[]}]}'
9.4 için , orijinal yanıtın değiştirilmiş bir sürümünü kullanabilirsiniz (aşağıda), ancak bir JSON dizesini toplamak yerine, doğrudan bir json nesnesine toplayabilirsiniz json_object_agg()
.
Orijinal cevap : Saf SQL'de de (plpython veya plv8 olmadan) mümkündür (ancak 9.3+'ye ihtiyaç duyar, 9.2 ile çalışmaz)
CREATE OR REPLACE FUNCTION "json_object_set_key"(
"json" json,
"key_to_set" TEXT,
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_to_set"
UNION ALL
SELECT "key_to_set", to_json("value_to_set")) AS "fields"
$function$;
SQLFiddle
Düzenle :
Birden çok anahtar ve değer ayarlayan bir sürüm:
CREATE OR REPLACE FUNCTION "json_object_set_keys"(
"json" json,
"keys_to_set" TEXT[],
"values_to_set" anyarray
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')::json
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> ALL ("keys_to_set")
UNION ALL
SELECT DISTINCT ON ("keys_to_set"["index"])
"keys_to_set"["index"],
CASE
WHEN "values_to_set"["index"] IS NULL THEN 'null'::json
ELSE to_json("values_to_set"["index"])
END
FROM generate_subscripts("keys_to_set", 1) AS "keys"("index")
JOIN generate_subscripts("values_to_set", 1) AS "values"("index")
USING ("index")) AS "fields"
$function$;
Düzenleme 2 : @ErwinBrandstetter'in belirttiği gibi yukarıdaki bu işlevler sözde gibi çalışır UPSERT
(varsa bir alanı günceller, yoksa ekler). İşte sadece bir varyant UPDATE
:
CREATE OR REPLACE FUNCTION "json_object_update_key"(
"json" json,
"key_to_set" TEXT,
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE
WHEN ("json" -> "key_to_set") IS NULL THEN "json"
ELSE (SELECT concat('{', string_agg(to_json("key") || ':' || "value", ','), '}')
FROM (SELECT *
FROM json_each("json")
WHERE "key" <> "key_to_set"
UNION ALL
SELECT "key_to_set", to_json("value_to_set")) AS "fields")::json
END
$function$;
Düzenleme 3 : Burada, UPSERT
bir anahtar yolunda bulunan (anahtarların yalnızca iç nesnelere başvurabildiği, iç dizileri desteklenmediği) bir yaprak değeri ayarlayabilen ( ve bu yanıttan ilk işlevi kullanan) özyinelemeli varyant :
CREATE OR REPLACE FUNCTION "json_object_set_path"(
"json" json,
"key_path" TEXT[],
"value_to_set" anyelement
)
RETURNS json
LANGUAGE sql
IMMUTABLE
STRICT
AS $function$
SELECT CASE COALESCE(array_length("key_path", 1), 0)
WHEN 0 THEN to_json("value_to_set")
WHEN 1 THEN "json_object_set_key"("json", "key_path"[l], "value_to_set")
ELSE "json_object_set_key"(
"json",
"key_path"[l],
"json_object_set_path"(
COALESCE(NULLIF(("json" -> "key_path"[l])::text, 'null'), '{}')::json,
"key_path"[l+1:u],
"value_to_set"
)
)
END
FROM array_lower("key_path", 1) l,
array_upper("key_path", 1) u
$function$;
Güncelleme : fonksiyonlar şimdi sıkıştırılmıştır.
select json_object_set_key((select data from test where data->>'b' = '2'), 'b', 'two');
Hata mesajını denediğimde bir hata görüyorumERROR: could not determine polymorphic type because input has type "unknown"