viernes, 28 de febrero de 2020

Pasar un JSON desde una Base de datos a un fichero de texto plano con formato JSON


Antes de nada tenemos que tener nuestro JSON almacenado en una base de datos. En este caso en lugar de almacenar toda la cadena JSON en un campo, hemos optado por almacenar cada nodo en una fila de la base de datos, de tal forma que cada fila deberá saber quien es su nodo padre.

La tabla empleada es de este tipo.

JSON almacenado en una Base de Datos


Debemos tener un código para cada nodo y otro para saber quien es el nodo padre, en otra columna almacenaremos los nombres de los nodos, y sus valores si los tienen. Como extra hemos añadido si son campos mandatory, o es un array.

Este es un ejemplo de cómo quedarían los datos en la tabla para un JSON genérico de Elastic Search.


Leerlo  desde la Base de datos y cargarlo en un Datagrid es bastante sencillo.

Creamos una pantalla de mantenimiento del DataGrid de este estilo.

Mantenimiento de una tabla

Este sería el Form_Load

Imports System.IO
Imports System.Data.OleDb
Imports System.Windows.Forms
Imports System.Data.SqlClient

Dim bolPrimeraVez As Boolean

Private Sub frmMantenimientoJSON_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.grdResult.DataSource = bs

        txtNodo.MaxLength = 40
        DefinicionJSON()

        Dim ObjetosPermitidos As Dictionary(Of String, String)
        ObjetosPermitidos = ComprobarPermisos(Me.Name)
        btnModificar.Visible = IIf(ObjetosPermitidos.ContainsKey("btnModificar"), True, False)
        btnBaja.Visible = IIf(ObjetosPermitidos.ContainsKey("btnBaja"), True, False)
        btnAlta.Visible = IIf(ObjetosPermitidos.ContainsKey("btnAlta"), True, False)
    End Sub



Aqui es donde lee de BBDD y lo pasa a un DataViewGrid (El DataGrid de la pantalla se llama grdresult).

 Sub DefinicionJSON()

        '  Dim dA As New OleDb.OleDbDataAdapter
        Dim tb As DataTable
        Dim srSQL As StreamReader
        Dim strConsulta As String
        Dim cmdbuilder As OleDbCommandBuilder


        tb = New DataTable

        ''Repeticion si no es la primera vez es que se ha llamado desde el mantenimiento y antes de cargarse debe borrarse la grid
        If Not bolPrimeraVez Then
            ds.Tables("DefinicionJSON").Clear()
        End If
        ''***********************

        strStartupPath = My.Application.Info.DirectoryPath
        srSQL = New System.IO.StreamReader(strStartupPath & "\CargarEsquemaJSON.sql")
        strConsulta = srSQL.ReadToEnd
        cmdPD = New OleDb.OleDbCommand(strConsulta, cnxPD)
        dA.SelectCommand = cmdPD
        cmdbuilder = New OleDbCommandBuilder(dA)
        dA.Fill(ds, "DefinicionJSON")

        If Not bolPrimeraVez Then
            Exit Sub
        End If

        bolPrimeraVez = False

        dA.UpdateCommand = cmdbuilder.GetUpdateCommand()
        dA.DeleteCommand = cmdbuilder.GetDeleteCommand()
        dA.InsertCommand = cmdbuilder.GetInsertCommand()

        bs.DataSource = ds.Tables(Tabla)

        Me.txtNodo.DataBindings.Add(New Binding("Text", bs, "COD_NODO_JSO"))
        Me.TxtNombreNodo.DataBindings.Add(New Binding("Text", bs, "DES_NODE"))
        Me.TxtNodoPadre.DataBindings.Add(New Binding("Text", bs, "COD_NODO_PAR"))
        Me.CboMandatory.DataBindings.Add(New Binding("Text", bs, "XTI_MANDATOR"))
        Me.CboReadOnly.DataBindings.Add(New Binding("Text", bs, "XTI_READ_ONL"))
        Me.txtUsuAuditoria.DataBindings.Add(New Binding("Text", bs, "AUD_USUARIO"))
        Me.txtFechaAuditoria.DataBindings.Add(New Binding("Text", bs, "AUD_TIM"

        grdResult.Columns(0).MinimumWidth = 100
        grdResult.Columns(1).MinimumWidth = 100
        grdResult.Columns(2).MinimumWidth = 100
        grdResult.Columns(3).MinimumWidth = 30
        grdResult.Columns(4).MinimumWidth = 30
        grdResult.Columns(5).MinimumWidth = 100
        grdResult.Columns(6).MinimumWidth = 100

        grdResult.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill

        grdResult.Columns(0).HeaderText = "Cod. Nodo"
        grdResult.Columns(1).HeaderText = "Nombre Nodo"
        grdResult.Columns(2).HeaderText = "Cod. Nodo Padre"
        grdResult.Columns(3).HeaderText = "Mandatory"
        grdResult.Columns(4).HeaderText = "Sólo lectura"
        grdResult.Columns(5).HeaderText = "Usuario Auditoria"
        grdResult.Columns(6).HeaderText = "Fecha Auditoria"
        grdResult.Refresh()

    End Sub

La SQL vendrá en el proyecto como CargarEsquemaJSON.sql y será una SELECT de este estilo:

SELECT  COD_NODO_JSO, DES_NODE, COD_NODO_PAR, XTI_MANDATOR, XTI_READ_ONL, AUD_USUARIO, AUD_TIM, DES_VALUE,XTI_ARRAY  FROM PROPIETARIO.TJSO order by COD_NODO_JSO


Este sería el código completo del programa:

Imports System.IO
Imports System.Data.OleDb
Imports System.Windows.Forms
Imports System.Data.SqlClient

Public Class frmMantenimientoJSON
    Dim ds As New DataSet()

    Dim bs As BindingSource = New BindingSource()
    Dim dA As New OleDb.OleDbDataAdapter
    Dim drEdit As DataRowView
    Dim bolRefrescar As Boolean
    Dim bolPrimeraVez As Boolean = True
    Const Tabla = "DefinicionJSON"

    Enum Accion
        Alta = 1
        Baja = 2
        Modificacion = 3
    End Enum

    Dim TipoAccion As Accion

    Private Sub frmMantenimientoJSON_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.grdResult.DataSource = bs

        txtNodo.MaxLength = 40

        DefinicionJSON()

        Dim ObjetosPermitidos As Dictionary(Of String, String)
        ObjetosPermitidos = ComprobarPermisos(Me.Name)
        btnModificar.Visible = IIf(ObjetosPermitidos.ContainsKey("btnModificar"), True, False)
        btnBaja.Visible = IIf(ObjetosPermitidos.ContainsKey("btnBaja"), True, False)
        btnAlta.Visible = IIf(ObjetosPermitidos.ContainsKey("btnAlta"), True, False)



    End Sub

    Sub DefinicionJSON()

        Dim tb As DataTable
        Dim srSQL As StreamReader
        Dim strConsulta As String
        Dim cmdbuilder As OleDbCommandBuilder


        tb = New DataTable

        ''Repeticion si no es la primera vez es que se ha llamado desde el mantenimiento y antes de cargarse debe borrarse la grid
        If Not bolPrimeraVez Then
            ds.Tables("DefinicionJSON").Clear()
        End If
        ''***********************

        strStartupPath = My.Application.Info.DirectoryPath
        srSQL = New System.IO.StreamReader(strStartupPath & "\CargarEsquemaJSON.sql")
        strConsulta = srSQL.ReadToEnd
        cmdPD = New OleDb.OleDbCommand(strConsulta, cnxPD)
        dA.SelectCommand = cmdPD
        cmdbuilder = New OleDbCommandBuilder(dA)
        dA.Fill(ds, "DefinicionJSON")

        If Not bolPrimeraVez Then
            Exit Sub
        End If

        bolPrimeraVez = False

        dA.UpdateCommand = cmdbuilder.GetUpdateCommand()
        dA.DeleteCommand = cmdbuilder.GetDeleteCommand()
        dA.InsertCommand = cmdbuilder.GetInsertCommand()

        bs.DataSource = ds.Tables(Tabla)

        Me.txtNodo.DataBindings.Add(New Binding("Text", bs, "COD_NODO_JSO"))
        Me.TxtNombreNodo.DataBindings.Add(New Binding("Text", bs, "DES_NODE"))
        Me.TxtNodoPadre.DataBindings.Add(New Binding("Text", bs, "COD_NODO_PAR"))
        Me.CboMandatory.DataBindings.Add(New Binding("Text", bs, "XTI_MANDATOR"))
        Me.CboReadOnly.DataBindings.Add(New Binding("Text", bs, "XTI_READ_ONL"))
        Me.txtUsuAuditoria.DataBindings.Add(New Binding("Text", bs, "AUD_USUARIO"))
        Me.txtFechaAuditoria.DataBindings.Add(New Binding("Text", bs, "AUD_TIM"))


        grdResult.Columns(0).MinimumWidth = 100
        grdResult.Columns(1).MinimumWidth = 100
        grdResult.Columns(2).MinimumWidth = 100
        grdResult.Columns(3).MinimumWidth = 30
        grdResult.Columns(4).MinimumWidth = 30
        grdResult.Columns(5).MinimumWidth = 100
        grdResult.Columns(6).MinimumWidth = 100

        grdResult.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill

        grdResult.Columns(0).HeaderText = "Cod. Nodo"
        grdResult.Columns(1).HeaderText = "Nombre Nodo"
        grdResult.Columns(2).HeaderText = "Cod. Nodo Padre"
        grdResult.Columns(3).HeaderText = "Mandatory"
        grdResult.Columns(4).HeaderText = "Sólo lectura"
        grdResult.Columns(5).HeaderText = "Usuario Auditoria"
        grdResult.Columns(6).HeaderText = "Fecha Auditoria"
        grdResult.Refresh()

    End Sub



    Private Sub btnFiltro_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFiltro.Click
        Dim strFiltro As String = ""
        Dim vwDefinicionJSON As DataView

        If txtFiltroNodo.Text <> "" Then
            If Not strFiltro = "" Then
                strFiltro = strFiltro & " AND "
            End If
            strFiltro = strFiltro & "COD_NODO_JSO LIKE '%" & txtFiltroNodo.Text & "%'" ' Name LIKE '%jo%'"
        End If

        If txtFiltroNombreNodo.Text <> "" Then
            If Not strFiltro = "" Then
                strFiltro = strFiltro & " AND "
            End If
            strFiltro = strFiltro & "DES_NODE LIKE '%" & txtFiltroNombreNodo.Text & "%'" ' Name LIKE '%jo%'"
        End If

        If txtFiltroNodoPadre.Text <> "" Then
            If Not strFiltro = "" Then
                strFiltro = strFiltro & " AND "
            End If
            strFiltro = strFiltro & "COD_NODO_PAR LIKE '%" & txtFiltroNodoPadre.Text & "%'" ' Name LIKE '%jo%'"
        End If

        If Not ds.Tables("DefinicionJSON") Is Nothing Then
            vwDefinicionJSON = ds.Tables("DefinicionJSON").DefaultView
            vwDefinicionJSON.RowFilter = strFiltro
        End If
    End Sub

    Private Sub btnAlta_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAlta.Click
        TipoAccion = Accion.Alta

        grbDetalle.Enabled = True
        grbBuscar.Enabled = False
        drEdit = bs.AddNew()
        bs.MoveLast()
        txtUsuAuditoria.Text = Environment.UserName
        txtFechaAuditoria.Text = Now
        grdResult.Refresh()
    End Sub

    Private Sub btnBaja_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBaja.Click
        Dim drv As DataRowView
        Dim b As Integer
        TipoAccion = Accion.Baja
        Try

            If MsgBox("¿Esta usted seguro que desea borrar este registro?", MsgBoxStyle.YesNo + MsgBoxStyle.Question, "Confirmación de Baja") = MsgBoxResult.Yes Then
                drv = bs.Current
                b = grdResult.CurrentRow.Index
                drv.Delete()
            End If
            dA.Update(ds, Tabla)
            grbDetalle.Enabled = False
            grdResult.Refresh()
        Catch ex As Exception
            If Mid(ex.Message, 1, 9) = "ORA-00001" Then
                MsgBox("El código de Nodo debe ser único revise los datos e intentelo de nuevo", MsgBoxStyle.Critical, "Error al actualizar los datos")
            End If
            If Mid(ex.Message, 1, 9) = "ORA-02292" Then
                MsgBox("No está permitido el borrado en cascada, asegurese que el nodo no tiene Sub-nodos antes de borrarlo", MsgBoxStyle.Critical, "Error al actualizar los datos")
            End If
            Recargar()
        End Try
    End Sub

    Private Sub btnModificar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnModificar.Click
        TipoAccion = Accion.Modificacion
        grbDetalle.Enabled = True
        grbBuscar.Enabled = False
        txtUsuAuditoria.Text = Environment.UserName
        txtFechaAuditoria.Text = Now
    End Sub

    Private Sub btnAceptar_Click(sender As Object, e As EventArgs) Handles btnAceptar.Click
        Dim drv As DataRowView
        Try
            drv = bs.Current
            bs.EndEdit()
            dA.Update(ds, Tabla)

            grbBuscar.Enabled = True
            grbDetalle.Enabled = False

            grdResult.Refresh()
            DefinicionJSON() 'refresca los cambios
            bolRefrescar = False
        Catch ex As Exception
            If Mid(ex.Message, 1, 9) = "ORA-00001" Then
                MsgBox("El código de nodo debe ser único revise los datos e intentelo de nuevo", MsgBoxStyle.Critical, "Error al actualizar los datos")
            End If
            bolRefrescar = True
        End Try
    End Sub
  

    Private Sub btnCancelar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancelar.Click
        bs.CancelEdit()
        If bolRefrescar Then
            Recargar()
        End If
        grbDetalle.Enabled = False
        grbBuscar.Enabled = True
    End Sub

    Sub Recargar()
        bolRefrescar = False
        ds.Tables(1).Clear()
        ds.Tables(0).Clear()
        DefinicionJSON()
        grdResult.Refresh()
    End Sub

    Private Sub txtColumna_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtNodo.TextChanged
        txtNodo.MaxLength = 8
    End Sub

    Sub AplicarFiltro()
        Dim strFiltro As String = ""
        Dim vwDefinicionJSON As DataView

        If txtFiltroNodo.Text <> "" Then
            If Not strFiltro = "" Then
                strFiltro = strFiltro & " AND "
            End If
            strFiltro = strFiltro & "COD_NODO_JSO LIKE '%" & txtFiltroNodo.Text & "%'" ' Name LIKE '%jo%'"
        End If

        If txtFiltroNombreNodo.Text <> "" Then
            If Not strFiltro = "" Then
                strFiltro = strFiltro & " AND "
            End If
            strFiltro = strFiltro & "DES_NODE LIKE '%" & txtFiltroNombreNodo.Text & "%'" ' Name LIKE '%jo%'"
        End If

        If txtFiltroNodoPadre.Text <> "" Then
            If Not strFiltro = "" Then
                strFiltro = strFiltro & " AND "
            End If
            strFiltro = strFiltro & "COD_NODO_PAR LIKE '%" & txtFiltroNodoPadre.Text & "%'" ' Name LIKE '%jo%'"
        End If

        If Not ds.Tables("DefinicionJSON") Is Nothing Then
            vwDefinicionJSON = ds.Tables("DefinicionJSON").DefaultView
            vwDefinicionJSON.RowFilter = strFiltro
        End If

    End Sub

    Private Sub txtFiltroNombre_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtFiltroNodo.TextChanged
        AplicarFiltro()
    End Sub

    Private Sub txtFiltroNombre_Validated(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtFiltroNodo.Validated
        ' AplicarFiltro()
    End Sub

    Private Sub txtFiltroDescripcion_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles txtFiltroNodoPadre.TextChanged
        AplicarFiltro()
    End Sub

    Private Sub cboFiltroAmbito_Validated(ByVal sender As Object, ByVal e As System.EventArgs)
        AplicarFiltro()
    End Sub

    Private Sub txtFiltroTipo_TextChanged(sender As Object, e As EventArgs) Handles txtFiltroNombreNodo.TextChanged
        AplicarFiltro()
    End Sub

  

    Private Sub grbFiltro_Enter(sender As Object, e As EventArgs) Handles grbFiltro.Enter

    End Sub

    Private Sub btnJSON_Click(sender As Object, e As EventArgs) Handles btnJSON.Click
        Dim d As New frmParseoJSON()  'envia los datos del grid al formulario hijo
        d.ShowDialog()
        d.WindowState = FormWindowState.Normal
    End Sub
End Class