Maison  >  Questions et réponses  >  le corps du texte

Créez une expression régulière pour ajouter des guillemets doubles aux parties d'une valeur JSON qui n'ont pas de guillemets doubles

<p>J'ai beaucoup de chaînes JSON mal formées, comme ceci : </p> <pre class="brush:php;toolbar:false;">{ "identifiant":23424938, "nom": unN, "réf":aN, "juil": unN, "chat":{}, "src":[], "Code": "SA", "type": d, "spéc":[i,j], "enfant": un }</pré> <p>J'essaie de créer une expression régulière pour citer une valeur JSON sans succès. </p> <p>J'ai fini par utiliser <code>/":([^"d{[]+?[^,}]?)/</code> qui a tout corrigé sauf les valeurs à l'intérieur du tableau, tel que <code>[i,j]</code>, il ne sera pas converti en <code>["i","j"]</code>. </p> <p>Pouvez-vous m'aider avec les valeurs entre parenthèses ? </p> <p>https://regex101.com/r/CGskmy/1</p>
P粉231112437P粉231112437400 Il y a quelques jours445

répondre à tous(1)je répondrai

  • P粉755863750

    P粉7558637502023-08-18 11:23:05

    Cette tâche sera quelque peu difficile en raison de l'ambiguïté. Par exemple, { "x": [y] } 是变成 { "x": "[y]" } 还是变成 { "x": ["y"] }?我会假设未加引号的字符串不包含 JSON 控制字符,例如 '[', ']', '{', '}', '"', ':', ','.

    Je pense que vous pouvez y parvenir en utilisant des groupes de capture nommés, qui est une fonctionnalité de PHP possible avec PCRE. Cela nécessite une certaine programmation pour effectuer le remplacement. L'opération preg_replace habituelle ne suffit pas car nous ne remplaçons pas toutes les allumettes.

    C'est la méthode que j'ai proposée. Tout d’abord, je fais correspondre les chaînes entre guillemets et je les ignore. Deuxièmement, je fais correspondre les chiffres et je les ignore. Enfin, je fais correspondre la chaîne sans guillemets et la stocke dans un groupe de capture appelé "sans guillemets". Notez que PCRE tentera de faire correspondre ces alternatives dans l'ordre dans lequel elles sont mises en correspondance. Les chaînes sans guillemets ne correspondent que si les chaînes et les nombres entre guillemets ne peuvent pas correspondre. C’est la clé de cette approche.

    Une fois que j'ai fait correspondre toutes les chaînes non citées, il suffit de concaténer la chaîne de sortie avec le remplacement. Cela se fait en parcourant les correspondances et en copiant les fragments de chaîne dans la sortie.

    <?php
    
    $in = <<<'IN'
    {
        "id":23424938,
        "name":aN,
        "ref":aN,
        "jul":aN,
        "cat":{},
        "src":[],
        "Code":"SA",
        "type":d,
        "spec":[i,j],
        "child":a
    }
    IN;
    
    // 在输入字符串上匹配。我们特别关注“unquoted”匹配组。
    $pattern = '/(?:"(?:\\"|[^"])+")|(?:[\d.]+)|(?P<unquoted>[^{}\[\]":,\s][^{}\[\]":,]*(?<!\s))/';
    preg_match_all($pattern, $in, $matches, PREG_UNMATCHED_AS_NULL | PREG_OFFSET_CAPTURE);
    
    // 输出字符串
    $out = '';
    
    // 跟踪输入字符串的当前索引
    $ix = 0;
    
    // 循环遍历所有未加引号的匹配项
    foreach ($matches['unquoted'] as $match) {
        $str = $match[0];
        $pos = $match[1];
        if ($str !== NULL) {
            // 将输入字符串复制到输出字符串
            $out .= substr($in, $ix, $pos - $ix);
            // 将匹配的字符串复制到输出字符串,用引号括起来
            $out .= '"' . $str . '"';
            // 更新输入字符串索引
            $ix = $pos + strlen($str);
        }
    }
    
    // 将输入字符串的尾部复制到输出字符串
    $out .= substr($in, $ix, strlen($in) - $ix);
    
    // 输出字符串
    echo $out;
    

    Je ne m'occupe pas de la syntaxe complète des nombres JSON, ni de la syntaxe JSON comme truefalsenull. J'espère que cette réponse est un point de départ et que vous pourrez la modifier en fonction de vos besoins.

    InSync fournit une expression régulière intéressante qui n'utilise pas de groupes de capture nommés mais demande à la place à PCRE d'ignorer les correspondances indésirables.

    (?:
      "(?:[^\"rrreee-\x1F\x7F]|\["\/bfnrt]|\u[\dA-Fa-f]{4})*"
    |
      -?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?
    )
    (*SKIP)(*FAIL)
    |
    [^{}[\]:,\s]+

    répondre
    0
  • Annulerrépondre