我可以从非严格的JSON中提取所选字段吗?
我的表是:
CREATE TABLE testme (id integer primary key, b json not null);
INSERT INTO testme(id,b) values (1,'{"similarartists":{"artist":[{"name":"x"},{"name":"y"}],"@attr":{"artist":"2H Company"}}}');
INSERT INTO testme(id,b) values (2,'{"similarartists":{"artist":{"name":"z"},"@attr":{"artist":"2H Company"}}}');
INSERT INTO testme(id,b) values (3,'{"similarartists":{"artist":"junk string","@attr":{"artist":"2H Company"}}}');
我的第一个想法是:
SELECT json_array_elements(b->'similarartists'->'artist')->'name' FROM testme;
但这是错误的。
答案 0 :(得分:1)
心理直觉告诉我,你的意思是当JSON结构对于表中的每一行都不统一时如何提取特定字段。
您发布的查询对示例中的任何行都无效,因为它们都没有在“similarartists”属性中有数组。但是,此查询至少对第1行有效:
SELECT json_array_elements(b->'similarartists'->'artist')->name
FROM testme where id=1;
在另外两行中 - 第一行包含一个相似的艺术家,另一行包含标量(“垃圾字符串”)。所以,我猜想(再次是通灵力量)想要你想做的就是:
使用9.3中提供的JSON支持,这是非常难以做到的。似乎没有一种简单的方法来推断JSON结构中数组元素属性的JSON类型。我在这里提出的解决方案似乎有效,但它远非优雅:
SELECT CASE substring((b->'similarartists'->'artist')::text,1,1)
WHEN '[' THEN json_array_elements(b->'similarartists'->'artist')->>'name'
WHEN '{' THEN b->'similarartists'->'artist'->>'name'
ELSE NULL
END AS artist
FROM testme;
查询正在检查提取的艺术家字段的字符串版本,以查看它是否以'[','{'或两者都没有。如果'''是一个艺术家阵列,你可以使用json_array_elements。如果它是'{'那么它就是一个艺术家。否则,它是垃圾,查询替换为NULL。当然,如果需要,你可以使用WHERE子句完全删除垃圾行。