• Publicidad

Obtener datos JSON

Así que programas sin strict y las expresiones regulares son otro modo de hablar. Aquí encontrarás respuestas de nivel avanzado, no recomendable para los débiles de corazón.

Obtener datos JSON

Notapor alperez » 2019-03-13 02:53 @162

Hola.

Estoy empezando a mirar toda esta parte de JSON debido a que se está mirando hacer consultas sobre RESTAPI y me han surgido dudas sobre JSON desde Perl. Sobre todo es a la hora capturar datos necesarios de las consultas y de cómo tratar la parte de JSON desde Perl.

Por ejemplo, tengo el siguiente código:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!C:\Perl64\bin
  2.  
  3. # Módulos
  4. use LWP::UserAgent;
  5. use JSON;
  6. use Data::Dumper;
  7.  
  8. my $json = JSON->new;
  9. my $ua = LWP::UserAgent->new
  10.         (
  11.         ssl_opts => { verify_hostname => 0, verify_peer => 0},
  12.     );
  13.  
  14.  
  15. my $content_type_v2 = "application/vnd.netbackup+json; version=2.0";
  16. my $token;
  17. my $hostname = "<ip>";
  18. my $base_url = "<url>";
  19. my $url = "$base_url/login";
  20.  
  21.  
  22. my $req = HTTP::Request->new(POST => $url);
  23. $req->header('content-type' => 'application/json');
  24. my $post_data = '{ "domainType": "unixpwd", "domainName": "<hostname>", "userName": "<user>", "password": "<pass>" }';
  25. $req->content($post_data);
  26. my $resp = $ua->request($req);
  27.  
  28. if ($resp->is_success)
  29. {
  30.         my $message = decode_json($resp->content);
  31.         $token = $message->{"token"};
  32.         print "Login succeeded with status code: ", $resp->code, "\n";
  33. }
  34. else
  35. {
  36.         print "HTTP POST error code: ", $resp->code, "\n";
  37.         print "HTTP POST error message: ", $resp->message, "\n";
  38. }
  39.  
  40. my $url = "$base_url/admin/jobs";
  41. print("URL --> *$url*\n");
  42.  
  43. my $req = HTTP::Request->new(GET => $url);
  44. $req->header('content-type' => $content_type_v2);
  45. $req->header('Authorization' => $token);
  46.  
  47. print "\n\n**************************************************************";
  48. print "\n\n Making GET Request to JOBS \n\n";
  49.  
  50. my $resp = $ua->request($req);
  51. if ($resp->is_success)
  52. {
  53.         #my $djson = decode_json($resp->content);
  54.         #print "JSON --> $json\n";
  55.         #my $attributes = $djson->{'data'}{'attributes'};
  56.         #print "Atributes --> $attributes\n";
  57.         #print Dumper $json;
  58.        
  59.         my $message = $resp->decoded_content;
  60.         #print Dumper $message;
  61.         #my $json_decoded = decode_json $message;
  62.                
  63.         # Guardamos los datos en la variable principal de perl y traducimos los datos a lo que necesitamos.
  64.         #$_ = $message;
  65.         #s/{"data":\[//g;
  66.         #s/{"links":\{"self":\{"href":"/\n/g; # quitamos los datos de la línea style
  67.         #s/{"href"://g;
  68.         #s/\},/\n/g;
  69.         #s/"//g;
  70.         #s/\}//g;
  71.         #s/\}//g;
  72.         #s/,/\n/g;
  73.         #$message=$_;
  74.                        
  75.         #print "List policy succeeded with status code: ", $resp->code, "\n";
  76.         print "Compact Json body for list policy: \n", $message, "\n\n";
  77.  
  78. }
  79. else {
  80.         print "HTTP GET error code: ", $resp->code, "\n";
  81.         print "HTTP GET error message: ", $resp->message, "\n";
  82. }
Coloreado en 0.004 segundos, usando GeSHi 1.0.8.4


En el código ahora mismo estoy sacando los datos tal cual me los devuelve la consulta que realizo y tengo comentado una limpieza de la salida para tener los datos más ordenados. Mi pregunta es si para la siguiente salida de datos hay alguna forma de sacar los campos dentro de "attributes" de alguna forma sencilla o es mejor limpiando como estoy haciendo.

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
{"data":[{"links":{"self":{"href":"/admin/jobs/42850"},"file-lists":{"href":""},"try-logs":{"href":""}},"type":"job","id":"42850","attributes":{"jobId":42850,"parentJobId":42846,"activeProcessId":22133,"mainProcessId":0,"productType":0,"jobType":"DBBACKUP","jobSubType":"IMMEDIATE","policyType":"NETBACKUP_CATALOG","policyName":"","scheduleType":"DIFFERENTIAL_INCREMENTAL","scheduleName":"Differential-Inc","clientName":"","controlHost":"","jobOwner":"root","jobGroup":"root","backupId":"","sourceMediaId":"","sourceStorageUnitName":"","sourceMediaServerName":"","destinationMediaId":"","destinationStorageUnitName":"","destinationMediaServerName":"","dataMovement":"","streamNumber":0,"copyNumber":0,"priority":0,"retention":3,"compression":0,"status":0,"state":"DONE","done":0,"numberOfFiles":981,"estimatedFiles":0,"kilobytesTransfered":42080,"kilobytesToTransfer":0,"transferRate":29406,"percentComplete":0,"currentFile":"","restartable":0,"suspendable":0,"resumable":0,"killable":0,"frozenImage":0,"transportType":"LAN","dedupRatio":0.0,"currentOperation":-2,"qReasonCode":-1,"qResource":"","robotName":"","vaultName":"","profileName":"","sessionId":0,"numberOfTapeToEject":0,"submissionType":0,"acceleratorOptimization":0,"dumpHost":"","instanceDatabaseName":"","auditUserName":"","auditDomainName":"","auditDomainType":0,"restoreBackupIDs":"","startTime":"2019-03-13T06:33:26.000Z","endTime":"2019-03-13T06:34:59.000Z","activeTryStartTime":"2019-03-13T06:33:26.000Z","lastUpdateTime":"2019-03-13T06:34:59.395Z","kilobytesDataTransferred":0,"try":1}},}
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4


Tampoco entiendo mucho el tema sobre todo de que esto me devuelve la referencia de un %HASH por lo que a mi entender debería de poder tratarlo como un hash pero no sé muy bien a la hora de realizar este tratamiento cómo hacerlo exactamente. He visto en algún mensaje en el foro que se usa "say" para imprimir los datos, pero tampoco entiendo cómo hacer la consulta directamente a las variables dentro del JSON, en este caso del campo "attributes".
alperez
Perlero nuevo
Perlero nuevo
 
Mensajes: 32
Registrado: 2013-11-14 17:48 @783

Publicidad

Re: Obtener datos JSON

Notapor explorer » 2019-03-13 07:01 @334

Lo primero que me dice el módulo JSON es que es json no está bien. Me falta un ']' hacia el final.
Este es el que estoy utilizando:
Sintáxis: [ Descargar ] [ Ocultar ]
Using javascript Syntax Highlighting
{"data":[{
    "links":{
        "self":{"href":"/admin/jobs/42850"},
        "file-lists":{"href":""},
        "try-logs":{"href":""}
    },
    "type":"job",
    "id":"42850",
    "attributes":{
        "jobId":42850,
        "parentJobId":42846,
        "activeProcessId":22133,
        "mainProcessId":0,
        "productType":0,
        "jobType":"DBBACKUP",
        "jobSubType":"IMMEDIATE",
        "policyType":"NETBACKUP_CATALOG",
        "policyName":"",
        "scheduleType":"DIFFERENTIAL_INCREMENTAL",
        "scheduleName":"Differential-Inc",
        "clientName":"","controlHost":"",
        "jobOwner":"root",
        "jobGroup":"root",
        "backupId":"",
        "sourceMediaId":"",
        "sourceStorageUnitName":"",
        "sourceMediaServerName":"",
        "destinationMediaId":"",
        "destinationStorageUnitName":"",
        "destinationMediaServerName":"",
        "dataMovement":"",
        "streamNumber":0,
        "copyNumber":0,
        "priority":0,
        "retention":3,
        "compression":0,
        "status":0,
        "state":"DONE",
        "done":0,
        "numberOfFiles":981,
        "estimatedFiles":0,
        "kilobytesTransfered":42080,
        "kilobytesToTransfer":0,
        "transferRate":29406,
        "percentComplete":0,
        "currentFile":"",
        "restartable":0,
        "suspendable":0,
        "resumable":0,
        "killable":0,
        "frozenImage":0,
        "transportType":"LAN",
        "dedupRatio":0.0,
        "currentOperation":-2,
        "qReasonCode":-1,
        "qResource":"",
        "robotName":"",
        "vaultName":"",
        "profileName":"",
        "sessionId":0,
        "numberOfTapeToEject":0,
        "submissionType":0,
        "acceleratorOptimization":0,
        "dumpHost":"",
        "instanceDatabaseName":"",
        "auditUserName":"",
        "auditDomainName":"",
        "auditDomainType":0,
        "restoreBackupIDs":"",
        "startTime":"2019-03-13T06:33:26.000Z",
        "endTime":"2019-03-13T06:34:59.000Z",
        "activeTryStartTime":"2019-03-13T06:33:26.000Z",
        "lastUpdateTime":"2019-03-13T06:34:59.395Z",
        "kilobytesDataTransferred":0,
        "try":1
    }
    }]
}
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Observa que hay ']' que cierra los datos de "data". Y sobraba una coma. Es posible que nos hayas puesto un resumen del json original.

Con este programa
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.14;
  3.  
  4. # Módulos
  5. use JSON;
  6. use Data::Dumper;
  7.  
  8. my $json = JSON->new;
  9.  
  10. open my $JSON_FH, '<', 'code_40951_1.json';
  11. my $message = decode_json(join "", <$JSON_FH>);
  12. close $JSON_FH;
  13.  
  14. say Dumper($message);
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
tenemos esta salida:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
$VAR1 = {
          'data' => [
                      {
                        'links' => {
                                     'file-lists' => {
                                                       'href' => ''
                                                     },
                                     'self' => {
                                                 'href' => '/admin/jobs/42850'
                                               },
                                     'try-logs' => {
                                                     'href' => ''
                                                   }
                                   },
                        'type' => 'job',
                        'attributes' => {
                                          'frozenImage' => 0,
                                          'destinationStorageUnitName' => '',
                                          'qReasonCode' => -1,
                                          'controlHost' => '',
                                          'sourceStorageUnitName' => '',
                                          'activeTryStartTime' => '2019-03-13T06:33:26.000Z',
                                          'percentComplete' => 0,
                                          'dataMovement' => '',
                                          'acceleratorOptimization' => 0,
                                          'suspendable' => 0,
                                          'sourceMediaServerName' => '',
                                          'retention' => 3,
                                          'dedupRatio' => '0',
                                          'clientName' => '',
                                          'endTime' => '2019-03-13T06:34:59.000Z',
                                          'backupId' => '',
                                          'destinationMediaId' => '',
                                          'currentFile' => '',
                                          'vaultName' => '',
                                          'kilobytesTransfered' => 42080,
                                          'dumpHost' => '',
                                          'activeProcessId' => 22133,
                                          'auditDomainName' => '',
                                          'numberOfTapeToEject' => 0,
                                          'profileName' => '',
                                          'sourceMediaId' => '',
                                          'jobSubType' => 'IMMEDIATE',
                                          'jobId' => 42850,
                                          'restartable' => 0,
                                          'numberOfFiles' => 981,
                                          'currentOperation' => -2,
                                          'mainProcessId' => 0,
                                          'resumable' => 0,
                                          'restoreBackupIDs' => '',
                                          'instanceDatabaseName' => '',
                                          'priority' => 0,
                                          'parentJobId' => 42846,
                                          'lastUpdateTime' => '2019-03-13T06:34:59.395Z',
                                          'compression' => 0,
                                          'state' => 'DONE',
                                          'scheduleName' => 'Differential-Inc',
                                          'destinationMediaServerName' => '',
                                          'kilobytesDataTransferred' => 0,
                                          'transportType' => 'LAN',
                                          'jobGroup' => 'root',
                                          'scheduleType' => 'DIFFERENTIAL_INCREMENTAL',
                                          'productType' => 0,
                                          'jobOwner' => 'root',
                                          'done' => 0,
                                          'startTime' => '2019-03-13T06:33:26.000Z',
                                          'streamNumber' => 0,
                                          'killable' => 0,
                                          'submissionType' => 0,
                                          'robotName' => '',
                                          'kilobytesToTransfer' => 0,
                                          'policyType' => 'NETBACKUP_CATALOG',
                                          'auditUserName' => '',
                                          'status' => 0,
                                          'sessionId' => 0,
                                          'policyName' => '',
                                          'copyNumber' => 0,
                                          'estimatedFiles' => 0,
                                          'auditDomainType' => 0,
                                          'try' => 1,
                                          'qResource' => '',
                                          'jobType' => 'DBBACKUP',
                                          'transferRate' => 29406
                                        },
                        'id' => '42850'
                      }
                    ]
        };
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
y ya vemos que tenemos el json traducido a una estructura compleja de datos (lo de compleja se refiere a que es más complicado que un escalar o un array o un hash).

Observa que empieza con un llave, así que hay que pensar en que tenemos una referencia a un hash.

Dentro de solo tiene una clave: "data". Y su valor es una ref. a un array.

Dentro de ese array vemos otra llave, así que suponemos que el contenido de ese array son ref. a hashes.

Dentro del primer hash, vemos las claves "id", "links", "type" y "attributes". De este último, vemos que su valor es una ref. a otro hash, que contiene toda la información que necesitamos.

De resultas de todo esto, podemos acceder a toda esta información con solo desreferenciar (cuando nos encontramos con una referencia) o usar un índice (cuando nos encontramos con un array).
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
say "ID:     ", $message->{'data'}[0]{'id'};
say "TYPE    ", $message->{'data'}[0]{'type'};
say "JOBTYPE ", $message->{'data'}[0]{'attributes'}{'jobType'};
say "STATE   ", $message->{'data'}[0]{'attributes'}{'state'};
say "START   ", $message->{'data'}[0]{'attributes'}{'startTime'};
say "END     ", $message->{'data'}[0]{'attributes'}{'endTime'};
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
ID:     42850
TYPE    job
JOBTYPE DBBACKUP
STATE   DONE
START   2019-03-13T06:33:26.000Z
END     2019-03-13T06:34:59.000Z
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

Como vamos a usar mucho la información de "attributes", podemos trabajar directamente con ese hash:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my $attributes_ref = $message->{'data'}[0]{'attributes'};

say $attributes_ref->{'policyType'};    # NETBACKUP_CATALOG
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4

Así manejamos el hash directamente a través de una desreferencia. Si queremos verlo como un hash real, entonces podemos sacar una copia a un hash nuestro:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
my %attributes = %{$message->{'data'}[0]{'attributes'}};

say $attributes{'transferRate'};        # 29406
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4


Obviamente, todo esto se refiere al primer elemento de 'data' (observa el '[0]'). Si hay más... pues entonces hay que hacer un bucle para recorrer todos esos elementos.

Más información en perllol, perlref y perlreftut.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Obtener datos JSON

Notapor alperez » 2019-03-13 08:28 @394

Hola.

Sí, perdona, el JSON que había adjuntado era un trozo de uno más grande.

Ahora ya me ha quedado claro para interpretar el contenido. Sin embargo me surgen varias dudas respecto a cómo realizar el recorrido. Es decir, en principio los datos necesarios para tratar siempre van a ser lo que vengan dentro de "attributes" en el caso de esta consulta. Lo que pasa que ese contenido estoy fijándome que para tratarlo de esta forma con hash, array... es muy tedioso ya que tengo que estar teniendo en cuenta varias cosas y recorrer con varios bucles, etc.

Mi duda es que mediante
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
$resp->decoded_content
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
puedo sacar el texto y de ahí limpiarlo hasta que me quede todo en un texto plano que luego puedo interpretar de una forma más sencilla. Por eso me surgía la duda, pero... ¿Qué sería más eficiente y sencillo?

Por que para poder recorrer tanto los hash como arrays internos dentro de los hash y luego el sucesivo hash debería desreferenciar cada dato cuando lo vaya leyendo, ¿no?
alperez
Perlero nuevo
Perlero nuevo
 
Mensajes: 32
Registrado: 2013-11-14 17:48 @783

Re: Obtener datos JSON

Notapor explorer » 2019-03-14 15:11 @674

alperez escribiste:¿Qué sería más eficiente y sencillo?
TODO el trabajo de limpiar, formatear y extraer la información del json, desde que es un texto, y convertirlo a una estructura jerárquica... es justo lo que hace el módulo JSON.

¿Vas a hacer algo que un módulo programado por otra persona ya ha hecho por ti?

alperez escribiste:Por que para poder recorrer tanto los hash como arrays internos dentro de los hash y luego el sucesivo hash debería desreferenciar cada dato cuando lo vaya leyendo, ¿no?

Bueno, sí... pero es fácil con la pista que te da Data::Dumper. A partir de lo que vemos en pantalla, podemos sacar este código que recorre todo los 'attributes' de todos los 'data':
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/env perl
  2. use v5.14;
  3.  
  4. # Módulos
  5. use JSON;
  6. use Data::Dumper;
  7.  
  8. my $json = JSON->new;
  9.  
  10. open my $JSON_FH, '<', 'code_40951_1.json';
  11. my $message = decode_json(join "", <$JSON_FH>);
  12. close $JSON_FH;
  13.  
  14. #say Dumper($message);
  15.  
  16. #say "ID:     ", $message->{'data'}[0]{'id'};
  17. #say "TYPE    ", $message->{'data'}[0]{'type'};
  18. #say "JOBTYPE ", $message->{'data'}[0]{'attributes'}{'jobType'};
  19. #say "STATE   ", $message->{'data'}[0]{'attributes'}{'state'};
  20. #say "START   ", $message->{'data'}[0]{'attributes'}{'startTime'};
  21. #say "END     ", $message->{'data'}[0]{'attributes'}{'endTime'};
  22.  
  23. # Recorrido por todas las fichas dentro de 'data'
  24. for my $data_ref ( @{ $message->{'data'} } ) {
  25.  
  26.     # Recorrido por todas las claves de 'attributes'
  27.     for my $atributo ( sort keys %{ $data_ref->{'attributes'} } ) {
  28.  
  29.         say "$atributo => $data_ref->{'attributes'}{$atributo}";
  30.     }
  31. }
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
En cinco líneas está resuelto. Aquí está el comienzo de lo que sale:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
acceleratorOptimization => 0
activeProcessId => 22133
activeTryStartTime => 2019-03-13T06:33:26.000Z
auditDomainName =>
auditDomainType => 0
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14480
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Obtener datos JSON

Notapor alperez » 2019-03-15 07:23 @349

Hola.

Al final no he dicho nada. Al principio me asusté un poco al revisar la cantidad de información pero luego es más sencillo recorrer las salidas y gestionarlas con las estructuras de datos que de la forma que había pensado al principio.

Muchas gracias por la ayuda y el empujón para entender cómo funcionan los JSON.
alperez
Perlero nuevo
Perlero nuevo
 
Mensajes: 32
Registrado: 2013-11-14 17:48 @783


Volver a Avanzado

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados