¿Puede preformatear un archivo de texto en datos JSON adecuados para que PBI lo reconozca como tal?

Un usuario Pregunto ✅

c4_disarm3r

Hola a todos.

Soy bastante nuevo en PowerBI, pero tengo algo de experiencia con otros servicios y software de visualización y análisis de datos.

Quiero crear un panel a partir de datos almacenados como JSON, pero no es un archivo JSON per se, ni un objeto JSON. Para explicarlo con más detalle, hay un software que almacena alertas como un objeto JSON y las agrega a un archivo de salida, sin usar delimitadores, como este:

{
    "metadata": {
        "customerID": "customer1",
        "alertID": 1234,
    },
    "event": {
        "UserIp": "1.1.1.1",
        "Success": true,
    }
}
{
    "metadata": {
        "customerID": "customer2",
        "alertID": 1235,
    },
    "event": {
        "UserIp": "1.1.1.2",
        "Success": false,
    }
}

No estoy muy familiarizado con JSON, pero estoy casi seguro de que los datos deberían delimitarse con [ ] y separados por comas (como una lista). No puedo hacer nada en el lado del software, por lo que la solución debería ejecutarse en PBI.

Una cosa que pensé fue agregar [ ] al principio y al final del archivo, y reemplace } con }, (los que aplican) usando Power Query, pero no funcionó …

Entonces, ¿cómo abordarías esto? Cualquier ayuda sería muy apreciada.

¡Muchas gracias por adelantado!,

c4

mahoneypat

Aquí hay una forma de hacer esto en el editor de consultas. Puede almacenar su archivo como texto y usar Text.FromBinary para abrirlo sin saltos de línea. Desde allí, puede usar Reemplazar valores para reparar el JSON y luego usar Json.Document para abrirlo. Para ver cómo funciona, simplemente cree una consulta en blanco, vaya al Editor avanzado y reemplace el texto allí con el código M a continuación, cambiando la línea de origen para que apunte a su archivo local.

let
    Source = Text.FromBinary(File.Contents("C:Testastext.txt")),
    #"Converted to Table" = #table(1, {{Source}}),
    #"Cleaned Text" = Table.TransformColumns(#"Converted to Table",{{"Column1", Text.Clean, type text}}),
    #"Trimmed Text" = Table.TransformColumns(#"Cleaned Text",{{"Column1", Text.Trim, type text}}),
    #"Replaced Value" = Table.ReplaceValue(#"Trimmed Text",",
    }","}",Replacer.ReplaceText,{"Column1"}),
    #"Replaced Value1" = Table.ReplaceValue(#"Replaced Value","}{","},{",Replacer.ReplaceText,{"Column1"}),
    #"Added Prefix" = Table.TransformColumns(#"Replaced Value1", {{"Column1", each "[" & _, type text}}),
    #"Added Suffix" = Table.TransformColumns(#"Added Prefix", {{"Column1", each _ & "]", type text}}),
    #"Added Custom" = Table.AddColumn(#"Added Suffix", "Custom", each Json.Document([Column1])),
    Custom = #"Added Custom"{0}[Custom],
    #"Converted to Table1" = Table.FromList(Custom, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table1", "Column1", {"metadata", "event"}, {"metadata", "event"}),
    #"Expanded metadata" = Table.ExpandRecordColumn(#"Expanded Column1", "metadata", {"customerID", "alertID"}, {"customerID", "alertID"}),
    #"Expanded event" = Table.ExpandRecordColumn(#"Expanded metadata", "event", {"UserIp", "Success"}, {"UserIp", "Success"}),
    #"Changed Type" = Table.TransformColumnTypes(#"Expanded event",{{"customerID", type text}, {"alertID", Int64.Type}, {"UserIp", type text}, {"Success", type logical}})
in
    #"Changed Type"

Saludos,

Palmadita

mahoneypat

Aquí hay una forma de hacer esto en el editor de consultas. Puede almacenar su archivo como texto y usar Text.FromBinary para abrirlo sin saltos de línea. Desde allí, puede usar Reemplazar valores para reparar el JSON y luego usar Json.Document para abrirlo. Para ver cómo funciona, simplemente cree una consulta en blanco, vaya al Editor avanzado y reemplace el texto allí con el código M a continuación, cambiando la línea de origen para que apunte a su archivo local.

let
    Source = Text.FromBinary(File.Contents("C:Testastext.txt")),
    #"Converted to Table" = #table(1, {{Source}}),
    #"Cleaned Text" = Table.TransformColumns(#"Converted to Table",{{"Column1", Text.Clean, type text}}),
    #"Trimmed Text" = Table.TransformColumns(#"Cleaned Text",{{"Column1", Text.Trim, type text}}),
    #"Replaced Value" = Table.ReplaceValue(#"Trimmed Text",",
    }","}",Replacer.ReplaceText,{"Column1"}),
    #"Replaced Value1" = Table.ReplaceValue(#"Replaced Value","}{","},{",Replacer.ReplaceText,{"Column1"}),
    #"Added Prefix" = Table.TransformColumns(#"Replaced Value1", {{"Column1", each "[" & _, type text}}),
    #"Added Suffix" = Table.TransformColumns(#"Added Prefix", {{"Column1", each _ & "]", type text}}),
    #"Added Custom" = Table.AddColumn(#"Added Suffix", "Custom", each Json.Document([Column1])),
    Custom = #"Added Custom"{0}[Custom],
    #"Converted to Table1" = Table.FromList(Custom, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Expanded Column1" = Table.ExpandRecordColumn(#"Converted to Table1", "Column1", {"metadata", "event"}, {"metadata", "event"}),
    #"Expanded metadata" = Table.ExpandRecordColumn(#"Expanded Column1", "metadata", {"customerID", "alertID"}, {"customerID", "alertID"}),
    #"Expanded event" = Table.ExpandRecordColumn(#"Expanded metadata", "event", {"UserIp", "Success"}, {"UserIp", "Success"}),
    #"Changed Type" = Table.TransformColumnTypes(#"Expanded event",{{"customerID", type text}, {"alertID", Int64.Type}, {"UserIp", type text}, {"Success", type logical}})
in
    #"Changed Type"

Saludos,

Palmadita

c4_disarm3r

En respuesta a mahoneypat

Muchas gracias, @mahoneypat.

¡Esto resuelve completamente mi problema!

c4

parry2k

@ c4_disarm3r ¿es esta la estructura de muestra json real? Parece puntos de datos incompletos y faltantes.

c4_disarm3r

En respuesta a parry2k

Hola @ parry2k, ¡feliz año nuevo!

Sí, así se estructuran los datos.

Desafortunadamente, así es como el software almacena los datos, simplemente agregando estas «alertas» en forma de un objeto JSON, pero sin formatear correctamente todo el archivo como JSON.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *