IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Parser un JSON


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mars 2016
    Messages : 5
    Par défaut Parser un JSON
    Bonsoir à tous,
    J'ai une question très bateau, mais je préfère demander l'avis de gens qui maîtrisent le sujet avant de faire n'importe quoi.
    J'ai besoin de parser ce fichier JSON: http://drive.google.com/open?id=1hCa...rN8mqky71JLMJP

    On me demande
    1) de parser tous les identifiants uniques du type "SV350".

    Le regex que je suggère est: "[A-Z]{2}[1-9]{3}":{
    Qu'en pensez-vous s'il vous plaît ?

    2) de parser tous les identifiants uniques du type "SV350" en ajoutant la condition "land":"ESP".
    La solution que je propose est: (?(?="land":"ESP")"[A-Z]{2}[1-9]{3}":{)
    Qu'en pensez-vous s'il vous plaît ? Je ne parviens pas à comprendre comment faire en sorte que ce soit le bon identifiant qui soit sorti et pas l'identifiant suivant par exemple.

    Merci d'avance pour votre aide,
    Nicolas.

  2. #2
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Tu compte pas parser le json comme une chaine de caractère a coup de regex quand même ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $datas = json_decode($chainejson,true);
    Va te donner un tableau de toutes les données que tu peux ensuite facilement parcourir pour appliquer le traitement que tu veux.

    http://php.net/manual/fr/function.json-decode.php
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mars 2016
    Messages : 5
    Par défaut
    Hello grunk,
    Merci pour ton retour.

    On me demande pas d'introduire du php dans cette histoire, à vrai dire on ne me demande pas le livrable final seulement le regex.
    Voilà les consignes exactes: https://drive.google.com/drive/folde...MHyB21lPgdudWl
    Il s'agit du 2.2

    Merci d'avance,
    Nicolas.

  4. #4
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Par défaut
    Citation Envoyé par Nicolas_LesPaul Voir le message
    On me demande
    1) de parser tous les identifiants uniques du type "SV350".

    Le regex que je suggère est: "[A-Z]{2}[1-9]{3}":{
    Qu'en pensez-vous s'il vous plaît ?
    Si aucune autre chaine n'a le même format dans ton json, ça devrait fonctionner. (sauf que les chiffres commencent à 0, pas à 1 )

    Citation Envoyé par Nicolas_LesPaul Voir le message
    2) de parser tous les identifiants uniques du type "SV350" en ajoutant la condition "land":"ESP".
    La solution que je propose est: (?(?="land":"ESP")"[A-Z]{2}[1-9]{3}":{)
    Qu'en pensez-vous s'il vous plaît ? Je ne parviens pas à comprendre comment faire en sorte que ce soit le bon identifiant qui soit sorti et pas l'identifiant suivant par exemple.
    Hum... là ça dépasse mes maigres compétences en regex.
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  5. #5
    Modérateur
    Avatar de grunk
    Homme Profil pro
    Lead dév - Architecte
    Inscrit en
    Août 2003
    Messages
    6 693
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Lead dév - Architecte
    Secteur : Industrie

    Informations forums :
    Inscription : Août 2003
    Messages : 6 693
    Par défaut
    Pour la première OK , je supprimerais la partie ":{" pour pas être embété avec d’éventuels espace qui pourraient être (ou non) présents.

    Pour la seconde comme Celira , je sais pas faire.

    Ceci étant dit c'est stupide de faire ce genre d'exercice sur du json , qui est un formatage justement pensé pour ne pas avoir à faire ça puisque largement intégré dans plein de langage.

    Pour tes tests de regex , tu peux utiliser https://regex101.com/ , très pratique !
    Pry Framework php5 | N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  6. #6
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mars 2016
    Messages : 5
    Par défaut
    Bonjour à tous,
    Merci pour vos retours !

    Pour le 1) on est d'accord que les parenthèses sont facultatives ?

    Pour le 2) il s'agit d'une syntaxe conditionnelle respectant le pcre ?

    Merci encore,
    Nicolas.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Administrateur systèmes et réseaux
    Inscrit en
    Mars 2016
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corrèze (Limousin)

    Informations professionnelles :
    Activité : Administrateur systèmes et réseaux
    Secteur : Associations - ONG

    Informations forums :
    Inscription : Mars 2016
    Messages : 5
    Par défaut
    Merci pour ton retour, cela dit inutile de monter sur tes grands chevaux.
    Si tu ne souhaites pas me répondre pour une raison x ou y, éh bien ne me réponds pas...
    J'ai pris soin de lire ton message avec attention, je n'y ai pas trouvé d'explication justifiant la nécessaire utilisation de parenthèses.

    Tiens, intéresse-toi à la notion de nexus savoir-pouvoir théorisée par Michel Foucault et mets ça en parallèle avec l'enseignement socratique sur les liens entre le savoir, l'intelligence et l'humilité.

  8. #8
    Modératrice
    Avatar de Celira
    Femme Profil pro
    Développeuse PHP/Java
    Inscrit en
    Avril 2007
    Messages
    8 633
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeuse PHP/Java
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2007
    Messages : 8 633
    Par défaut
    Pour autant que je sache, les parenthèses servent à capturer un groupe de façon pouvoir l'extraire ou le remplacer. Donc si le but est uniquement de vérifier si l'expression est valide, les parenthèses ne sont pas nécessaires.
    Modératrice PHP
    Aucun navigateur ne propose d'extension boule-de-cristal : postez votre code et vos messages d'erreurs. (Rappel : "ça ne marche pas" n'est pas un message d'erreur)
    Cherchez un peu avant poser votre question : Cours et Tutoriels PHP - FAQ PHP - PDO une soupe et au lit !.

    Affichez votre code en couleurs : [CODE=php][/CODE] (bouton # de l'éditeur) et [C=php][/C]

  9. #9
    Expert confirmé Avatar de CosmoKnacki
    Homme Profil pro
    Justicier interdimensionnel
    Inscrit en
    Mars 2009
    Messages
    2 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Justicier interdimensionnel

    Informations forums :
    Inscription : Mars 2009
    Messages : 2 986
    Par défaut
    Je ne sais pas trop comment prendre "Please check it[']s structure first": S'agit-il de vérifier en premier lieu si la chaîne est bien du JSON? Dans ce cas, tu peux utiliser cette pattern:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    $json = file_get_contents('sample.json');
    $pattern = <<<'EOD'
    ~
    (?(DEFINE)
        (?<number> -?(?:[1-9][0-9]*(?:\.[0-9]+)?|0(?:\.[0-9]+)?)(?:[eE][-+]?[0-9]+)? )
        (?<null> null )
        (?<boolean> true | false )
        (?<string> " [^"\\]*+ (?:\\.[^"\\]*)*+ " )
     
        (?<list> \[ \s* (?: \g<value> (?: \s* , \s* \g<value> )*+ )?+ \s* ] )
        (?<object> { \s* (?: \g<keyval> (?: \s* , \s* \g<keyval> )*+ )?+ \s* } )
     
        (?<value> \g<number> | \g<null> | \g<boolean> | \g<string> | \g<list> | \g<object> )
        (?<keyval> \g<string> \s* : \s* \g<value> )
    )
     
    \A \g<object> $
     
    ~x
    EOD;
    var_dump(preg_match($pattern, $json)); // int(1)
    Remarques à propos de ce code:
    • Cette pattern est en deux parties: la première partie (?(DEFINE) ... ) définie les différents éléments à l'aide de groupes nommés ainsi que leurs rapports entre eux: un groupe peut se définir par rapport à un autre groupe voire à lui même, ce qui éventuellement implique une structure récursive (comme l'est le JSON). Cette première partie sert juste à nommer les choses et à établir des rapports entre elles, mais concrètement c'est une sous-pattern vide, elle ne matche rien (zero-width assertion) et n'impose rien non plus comme le ferait un test avant (lookahead) ou arrière (lookbehind) ou encore une ancre (^, $, \A, \z).
      La seconde partie \A \g<object> $ est la pattern comme on l'entend communément, c-à-d la description de la chaîne en elle-même, et ce, même si elle fait référence aux éléments précédemment définis.
    • Comme pcre est un moteur à backtracking et afin de limiter celui-ci (le backtracking), nombre de quantificateurs sont passés en "possessif" (?+, *+, ++). Ceci dit, l'impact de cette mesure reste à nuancer puisque une des particularités de pcre (contrairement à Perl) est de rendre atomique tout appel à une sous-pattern. Concrètement, si je fais un appel à, disons, \g<number> et que celui-ci réussi, il ne sera plus possible d'effectuer un backtracking sur les caractères consommés par \g<number> si la sous pattern suivante échoue, sauf à éliminer l'appel en question d'un seul bloc.
    • J'utilise l'ancre $ au lieu de l'ancre \z car elle est plus permissive (celle-ci réussit dans deux cas: soit à la fin de la chaîne, soit juste avant le dernier caractère de la chaîne quand celui-ci est un \n, alors que \z matche strictement la fin de la chaîne). Or il se trouve que ton fichier json se termine par un \n juste après la dernière accolade fermante. On aurait aussi pu écrire \A \g<object> \n? \z ou encore \A \g<object> \s* \z.
    • La pattern est écrite pour décrire un format JSON de la manière la plus laxe possible, c'est à dire qu'elle autorise entre chaque token un nombre quelconque de caractères blancs. C'est pourquoi les sous-patterns sont parsemées de \s*. Mais dans ton cas, il semblerait que tous ces espaces blancs inutiles ne sont pas présents. Donc tu peux éventuellement enlever tous ces \s*. À toi de voir.
    • Pour écrire cette pattern en php, j'ai utilisé la syntaxe NOWDOC. Bien entendu, si je devais l'écrire entre quotes simples ou doubles, je devrais remplacer tous les \\ par \\\\. Maintenant je n'ai aucune idée du format attendu pour ton exercice, mais d'instinct j'utiliserai celui de la syntaxe NOWDOC.



    Pour obtenir toutes les clefs, il suffit de remplacer la pattern principale:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    $pattern = <<<'EOD'
    ~
    (?(DEFINE)
        (?<number> -?(?:[1-9][0-9]*(?:\.[0-9]+)?|0(?:\.[0-9]+)?)(?:[eE][-+]?[0-9]+)? )
        (?<null> null )
        (?<boolean> true | false )
        (?<string> " [^"\\]*+ (?:\\.[^"\\]*)*+ " )
     
        (?<list> \[ \s* (?: \g<value> (?: \s* , \s* \g<value> )*+ )?+ \s* ] )
        (?<object> { \s* (?: \g<keyval> (?: \s* , \s* \g<keyval> )*+ )?+ \s* } )
     
        (?<value> \g<number> | \g<null> | \g<boolean> | \g<string> | \g<list> | \g<object> )
        (?<keyval> \g<string> \s* : \s* \g<value> )
    )
    (?:
        \G(?!\A) : \g<object> ,
      |
        \A
        { "objekte" :
            {
                (?: \g<keyval> (?: \s* , \s* \g<keyval>)*? , "objekte" : | "objekte" : ) {
    )
    " (?<ID> [^"\\]*+ (?:\\.["\\]*)*+ ) "
    ~x
    EOD;
    if ( preg_match_all($pattern, $json, $matches) ) {
        print_r($matches['ID']);
    }
    Il s'agit là d'une structure classique utilisant l'ancre \G qui matche la position qui suit une correspondance réussie: (?: \G(?!\A) (?# préfixe des correspondances suivantes )| (?# prefixe de la première correspondance ) ) (?# ce que l'on veut ). Cette structure permet de rechercher des correspondances contiguës.

    Ensuite reste à filtrer, toutes les annonces qui ne sont pas localisées en Espagne. Pour réussir cela, il suffit de consommer toutes les annonces des autres pays avant en prenant le soin de placer l'ensemble des annonces non-voulues dans un groupe auquel on applique un quantificateur possessif pour ne pas subir le backtracking.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    $pattern = <<<'EOD'
    ~
    (?(DEFINE)
        (?<number> -?(?:[1-9][0-9]*(?:\.[0-9]+)?|0(?:\.[0-9]+)?)(?:[eE][-+]?[0-9]+)? )
        (?<null> null )
        (?<boolean> true | false )
        (?<string> " [^"\\]*+ (?:\\.[^"\\]*)*+ " )
     
        (?<list> \[ \s* (?: \g<value> (?: \s* , \s* \g<value> )*+ )?+ \s* ] )
        (?<object> { \s* (?: \g<keyval> (?: \s* , \s* \g<keyval> )*+ )?+ \s* } )
     
        (?<value> \g<number> | \g<null> | \g<boolean> | \g<string> | \g<list> | \g<object> )
        (?<keyval> \g<string> \s* : \s* \g<value> )
    )
    (?:
        \G(?!\A) : \g<object> ,
      |
        \A
        { "objekte" :
            {
                (?: \g<keyval> (?: \s* , \s* \g<keyval>)*? , "objekte" : | "objekte" : ) {
    )
    (?:
        \g<string> : {
        (?: \g<keyval> (?: \s*, \g<keyval> )*? , "land" : | "land" : ) (?!"ESP") \g<value>
        (?: , \g<keyval> )* } ,
     
    )*+
    " (?<ID> [^"\\]*+ (?:\\.["\\]*)*+ ) "
    ~x
    EOD;
    if ( preg_match_all($pattern, $json, $matches) ) {
        print_r($matches['ID']);
    }
    ps: inutile de t'acharner à tester ces codes sur des testeurs en ligne car la chaîne est trop longue et les patterns trop complexes. Ceci dit, je rejoins Grunk en ce qui concerne l'intérêt pédagogique de s'entraîner aux regex sur des données structurées comme le JSON ou le html, alors que dans la vrai vie, il y a des parsers prévus à cet effet. (Je mettrai d'ailleurs au passage, dans le même sac les exemples de poo illustrés par des bagnoles avec options).

Discussions similaires

  1. [Prototype] Parser du JSON aprés une requête Ajax
    Par Gregory.M dans le forum Bibliothèques & Frameworks
    Réponses: 18
    Dernier message: 16/06/2010, 10h21
  2. parser un json
    Par Henry9 dans le forum jQuery
    Réponses: 4
    Dernier message: 18/05/2009, 21h13
  3. Réponses: 1
    Dernier message: 09/12/2007, 17h44
  4. [Débutant] Parser et réordonner une chaîne de caractères
    Par Ykaar dans le forum Windows Forms
    Réponses: 6
    Dernier message: 02/06/2007, 12h51
  5. [débutant] Parser java
    Par hariri dans le forum Format d'échange (XML, JSON...)
    Réponses: 2
    Dernier message: 10/05/2007, 13h02

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo