Ajuda com formatação de arquivo Json para inserção no PostgreSQL

Salve comunidade, espero que estejam todos bem. Tenho um projeto particular a título de estudo e estou com o seguinte cenário:

Possuo esse arquivo json que obtenho de uma simples api com uso do crontab e wget de forma que o arquivo resultado vem formatado, com espaços e tudo mais.

Pesquisando na internet cheguei nesse código py que realiza a inserção dos dados na base(Postgresql) em uma coluna do tipo json.

Para que o código funcione tenho que retirar o seguinte trecho (inclusive as chaves e colchetes)
{
“type”: “FeatureCollection”,
“features”: […]
}

O conteúdo que me interessa e que desejo inserir no banco está em “features” e é separado por vírgula (<-), como no exemplo:
{
“type”: “Feature”,
“Id”: “02900c40-0e95-4369-b9c4-22b2233a3440” …
} , ←
{
“type”: “Feature”,
“Id”: “900000118_parkinglocation” …
}

Como teste criei um arquivo com somente um trecho {“type”:“Feature”,“Id”:“900000118_parkinglocation” …} que foi manualmente editado e o código funcionou “perfeitamente”, ou seja, consegui inserir na base e trabalhar com os dados no pg.

Como não sou programador py peço dicas de código para que eu consiga retirar o trecho desnecessário, retirar todos os espaços que não estejam dentro de uma string e inserir no banco o que está entre cada virgula.

Em resumo, transformar isso
original

Nesse formato

Obrigado !

Olá @Alexandre

Fiz um exemplo me baseando nos dados que você forneceu.

Bom no Python um arquivo Json é convertido para o tipo dicionário e o acesso aos dados é feito acessando as chaves do arquivo ({chave: valor}, {chave: {chave: valor}}, {chave: [lista de valores]}).

Criei um arquivo chamado arquivo_json.json com os dados que você forneceu:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "Id": "02900c40-0e95-4369-b9c4-22b2233a3440",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    4.915205,
                    52.377864
                ]
            },
            "properties": {
                "Name": "CE-P28 PTA Touringcars",
                "PubDate": "2019-10-21T01:14:41.972Z",
                "Type": "parkinglocation",
                "State": "ok",
                "FreeSpaceShort": "0",
                "FreeSpaceLong": "",
                "ShortCapacity": "42",
                "LongCapacity": ""
            }
        },
        {
            "type": "Feature",
            "Id": "900000118_parkinglocation",
            "geometry": {
                "type": "Point",
                "coordinates": [
                    4.92911,
                    52.35694
                ]
            },
            "properties": {
                "Name": "CE-P20 Oostpoort",
                "PubDate": "2019-10-21T01:14:41.972Z",
                "Type": "parkinglocation",
                "State": "ok",
                "FreeSpaceShort": "319",
                "FreeSpaceLong": "0",
                "ShortCapacity": "373",
                "LongCapacity": "0"
            }
        }
    ]
}

O fato do aquivo estar formatado (com espaços) como você descreveu não é um problema é apenas uma forma de ficar legível para ‘humanos’, contudo durante a execução do código fiz um print() onde os dados são exibidos sem formatação.

Como não faço ideia da sua estrutura de tabela(s) eu fiz uma simulação utilizando uma tabela que possui uma coluna id (chave primaria) e uma coluna dict do tipo JSONB.

Você disse em seu texto que você não é programador, então fiz um código bem linear, sem criar classes, métodos, funções, etc.

# -*- coding: utf-8 -*-
"""Exemplo, adeque conforme as suas necessidades.

Para instalar o psycopg2_ pode-se utilizar:

.. _psycopg2: http://initd.org/psycopg/

.. code-block:: bash

    pip install psycopg2-binary
"""

import json

from psycopg2 import connect
from psycopg2.extras import Json

# Abrindo o arquivo (pode-se utilizar o ``with open()``).
json_file = open(file='arquivo_json.json')

# Lendo o arquivo como Json.
data = json.load(json_file)

# Fechando o arquivo, visto que ele não é mais necessário.
json_file.close()

# Exibindo os dados que estão na chave `features`.
# Utilizando o Loop ``for``` porque os dados
# estão contido em uma lista.
for values in data['features']:
    print(f'\n{values}\n----')

# Criando a conexão com o banco.
# Para teste utilizei o https://www.elephantsql.com/.
con = connect(
    user='gsrndmds',
    password='kXOmIUIfsfUmcjCNIzAB22vZQ8C6U7vA',
    host='salt.db.elephantsql.com',
    port='5432',
    dbname='gsrndmds',
)

# Criando o cursor que irá executar os
# comandos SQL (instruções DML, DDL, etc).
cur = con.cursor()

# Removendo a tabela.
# Estou removendo a tabela para não
# ficar repetido os dados toda hora.
query = f'DROP TABLE IF EXISTS nome_da_tabela'
try:
    cur.execute(query)
except Exception as e:
    print(f'\n[x] Falha ao remover a tabela [x]: {e}')
else:
    con.commit()
    print('\n[!] Tabela removida com sucesso [!]')

# Criando a tabela caso ela não exista.
# Caso você já tenha a tabela é só ignorar essa parte.
create_table = '''CREATE TABLE IF NOT EXISTS nome_da_tabela (
_id     SERIAL  NOT NULL,
dict    JSONB,
PRIMARY KEY(_id)
);'''
try:
    cur.execute(create_table)
except Exception as e:
    print(f'\n[x] Falha ao criar a tabela [x]: {e}')
else:
    print('\n[!] Tabela criada com sucesso [!]')

# Exibindo os dados da tabela ANTES da inserção.
query = 'SELECT * FROM nome_da_tabela LIMIT 100'
cur.execute(query)
print(f'Dados da tabela antes: {cur.fetchall()}\n----')

# Query que irá inserir os dados.
query = 'INSERT into nome_da_tabela (dict) values (%s)'
# Loop para percorrer todos os dados que estão na lista.
for values in data['features']:
    # Salvando os dados no banco.
    cur.execute(query, [Json(values)])

# Exibindo os dados da tabela DEPOIS da inserção.
query = 'SELECT * FROM nome_da_tabela LIMIT 100'
cur.execute(query)
print(f'Dados da tabela após: {cur.fetchall()}\n---')

# Fechando a conexão com o banco.
con.close()

Eu utilizei try e except para controlar os erros, contudo isso não é necessário dependendo do seu cenário.

Os dados de conexão do PostgreSQL que estão no código são válidos, vou deixá-los ativos por alguns dias assim você pode testar.

Caso queira ver alguns exemplos de conexão com banco de dados basta acessar o meu Github.

1 curtida

Boa Noite @natorsc,

Cara, antes de mais nada gostaria de agradecer pela resposta e dizer que funcionou exatamente da maneira como eu esperava e queria, valeu mesmo.

Eu pedi ajuda pois python não é meu forte (tenho conhecimento em Java, C e SQL) e a maior dificuldade estava exatamente nisso:

cur.execute(query, [Json(values)])

Apenas para esclarecer, os dados são dessa API que foi encontrada nessa lista.

Mais uma vez obrigado !

1 curtida

Muito interessante essa API!

Valeu mesmo por compartilhar ela.

E realmente você disse que não era programador Python e não que não era programador kkkkk. Falha total na minha leitura :sweat_smile: :joy:.