69

I have a TEXT column containing valid JSON string.

CREATE TABLE users(settings TEXT);

INSERT INTO users VALUES ('{"language":"en","gender":"male"}');
INSERT INTO users VALUES ('{"language":"fr","gender":"female"}');
INSERT INTO users VALUES ('{"language":"es","gender":"female"}');
INSERT INTO users VALUES ('{"language":"en","gender":"male"}');

I want to transform some fields into a query-able format.

A REGEXP_REPLACE for each field would do (language field and gender field). But since it's valid JSON, is there way to:

  • Convert into JSON type
  • Convert into hstore type
  • Or any other feasible ways

SQLFiddle: http://sqlfiddle.com/#!12/54823

4

7 回答 7

75
SELECT cast(settings AS json) from users;

7年后编辑

我强烈建议您不要使用非结构化列,除非您的数据是非结构化的。RDBMS 有很长的路要走。我们搭建了一个相当大的平台,将用户设置作为一个json列,最终变成了一个需要多年后清理的垃圾抽屉

于 2014-04-17T01:11:22.087 回答
69

或者以比 Reza 最短的方式:

SELECT settings::json FROM users;

然后,例如选择语言:

SELECT settings::json->>'language' FROM users;

有关官方文档的更多详细信息。

于 2014-10-02T07:58:15.087 回答
20

这是Postgresql 的解决方案:Converting TEXT columns to JSON

ALTER TABLE table1 ALTER COLUMN col1 TYPE JSON USING col1::JSON;
于 2015-07-18T17:09:13.393 回答
9

所以我遇到了文本是 JSON 的问题。如果您有此问题,请改用此查询。其中 COLUMN 是包含 JSONB 或 JSON 数据类型的列,ATTRIBUTE 是 JSON 的属性,它是一个字符串,您希望将其转换为 JSON。

文本将如下所示,"{\"junk5\": 283774663, \"junk2\": 0, \"junk1\": 1218478497, \"junk3\":1923, \"junk4\": 63278342}"

SELECT CAST(TRIM(both '"' from jsonstring) as JSON)
FROM (
    SELECT REPLACE(cast(COLUMN->'ATTRIBUTE' as text), '\"', '"')
    as jsonString from TABLE where cast(COLUMN->'ATTRIBUTE' as text)LIKE '%\\%'
) as JSON_CONVERTING
于 2019-02-01T20:43:32.483 回答
4

如果您的列已经是 json 并且在其根级别包含字符串,则该::jsonb列将不起作用。这是一个将此类字符串转换为 JSON 的衬垫:

SELECT (settings #>> '{}')::jsonb -> 'language' from users;

我在这里找到了这个答案

#>>该语句首先通过给定空路径的运算符将根级字符串提取为文本。请注意,简单地将此类字符串转换为文本 ( ::text) 是行不通的,因为它会转义所有引号。接下来,将提取的字符串解析为 json 对象 ( ::jsonb)。

此查询的另一种版本是将 json 字符串放入数组中,然后将其第一个元素提取为文本:

选择 cast(json_build_array(settings)->>0 as json)

要解决此问题,您还可以使用以下命令将所有带有根级别字符串的字段转换为 json:

UPDATE users
SET
    settings = settings #>>'{}'::jsonb
WHERE settings ->> 'language' is  NULL
于 2021-08-06T09:47:41.407 回答
3

如果您需要对其进行索引,请创建一个不可变函数,该函数将 json 作为输入并以 pl 语言生成您想要作为输出的字段,例如:

create function extract_language(text) returns text as $$
  -- parse $1 as json
  -- return $1.language
$$ language whatever immutable;

然后在表达式上添加一个索引:

create index users_language on users(extract_language(settings));

然后,该索引将(可能)用于以下查询:

select * from users where extract_language(settings) = 'en';
于 2013-04-27T09:12:02.287 回答
2

添加到另一条评论,这是一个查询中的单行符(无需更新)

regexp_replace(trim(both '"' from settings::text), '\\"', '"', 'g')::json as column_name;
于 2020-08-07T19:14:14.497 回答