如何在postgresql中将json对象作为列?

时间:2016-10-09 15:33:17

标签: json postgresql

我在mu PostgreSQL 9.05上有这些表:

表:core 字段:namedescriptiondata

data字段是一个json字段,(例如):{"id": "100", "tax": "4,5"}

每个数据始终为one json。

我的问题是:我可以将所有JSON字段作为查询字段吗?像这样返回:name, description, id, tax....

问题是:我的JSON确实有各种字段,可以是Id,tax或其他。

3 个答案:

答案 0 :(得分:8)

你不能“动态地”做到这一点。您需要指定要包含的列:

in

如果你做了很多,你可能想把它放到一个视图中。

另一种选择是在Postgres中创建一个表示JSON中属性的对象类型,例如:

>>> all(e in s for e in ('24','England'))
True
>>> any(e in s for e in ('France','England'))
True
>>> all(e in s for e in ('France','England'))
False

然后,您可以将JSON强制转换为该类型,并且JSON中的相应属性将自动转换为列:

使用上述类型和以下JSON:select name, description, id, data ->> 'tax' as tax, data ->> 'other_attribute' as other_attribute from core; ,您可以执行以下操作:

create type core_type as (id integer, tax numeric, price numeric, code varchar);

它会返回:

{"id": "100", "tax": "4.5", "price": "10", "code": "YXCV"}

但是你需要确保每个JSON值都可以转换为相应对象字段的类型。

如果更改对象类型,则会自动更新使用它的任何查询。因此,您可以通过中央定义管理您感兴趣的列。

答案 1 :(得分:4)

从PostgreSQL 9.4开始,您也可以使用json_to_record

  

从JSON对象构建任意记录(请参阅下面的注释)。与返回记录的所有函数一样,调用者必须使用AS子句显式定义记录的结构。

例如:

 a |    b    | d
---+---------+---
 1 | [1,2,3] |

返回

{{1}}

答案 2 :(得分:0)

我觉得很烦人,没有人找到合适的解决方案。

将 OP 问题解读为:“给定一个具有 JSON 字段的表,具有不同的键,并且没有预先知道这些键的存在或身份,我如何将这些值作为统一记录集的一部分获取?”

>

理想情况下,解决方案将在单个脚本中完成此操作,可用作应用程序的视图或源,但以下内容在存储过程中很有用,或者如果您的 JSON 架构很少更改。

select
    concat_ws(
        ' ',
        e'select\n\t*,',
        string_agg(
            distinct concat(
                e'\tcase ',e'json_field?\'', json_column_key, e'\'\n\t\t',
                e'when true then json_field->\'', json_column_key,e'\'\n\t\t',
                e'else NULL\n\t',
                'end as ',json_column_key,
            ),
             e',\n\t'
        ),
        e'\nfrom table_with_json'
    ) as generated_sql_script
from (
    select json_object_keys(annotations) as json_column_key
    from table_with_json.answers
    where json_typeof(json_field) like 'object'
) as generate_promoted_json

输出是一个记录集,描述父表中的所有列,包括具有 json 对象的列,但每个属性都有单独的列,这些列可能存在也可能不存在于特定记录中。

一些不足:

  1. 上面没有指定分解数据的类型。这可能是一个问题,可能值得修改脚本以反映这一点。
  2. 这不涉及二级对象和数组。如果这些存在于您的架构中,并且它们有所不同,则可能需要扩展此脚本以包含该逻辑,可能会将其降级为从准备生成的查询的假设存储过程中执行的一系列函数。

除此之外,它应该是一个通用的实用程序。