Extract joint data from a JSON using PHP

Asked

Viewed 37 times

0

I have the following JSON structure

{
  "trophy_name_XPT001": "Text Name 01",
  "trophy_desc_XPT001": "Text Desc 01",
  "throw.except.und": "Error",
  "nav_bunt_852": "Zoom Out",
  "trophy_name_BHTLN": "Text Name 02",
  "trophy_desc_BHTLN": "Text Desc 02",
  "trophy_name_XPT020": "Text Name 03",
  "trophy_desc_XPT020": "Text Desc 03",
  "abc_gama_opt": "Text Random",
  "inpt.hover.ali": "11.02.22.456-896",
  "trophy_name_OPB852": "Text Name 04",
  "trophy_desc_OPB852": "Text Desc 04",
  "trophy_name_XPTHJN": "Text Name 06",
  "trophy_desc_XPTHJN": "Text Desc 06",
  "trophy_name_XPT002": "Text Name 008*01",
  "trophy_desc_XPT002": "Text Desc 008*01",
  "nav_admin": "89652"
}

I need to filter only the data that contains trophy_name_... and trophy_desc_... and use a foreach to iterate and merge the same code into a single array

At the moment the code is this

<?php

$json = json_decode(file_get_contents("texts.json"));

foreach ($json as $key => $value) {
    if (preg_match_all("/trophy_(name|desc)_(.*.)/", $key, $matches)) {

        $type = $matches['1']['0'];
        $code = $matches['2']['0'];
    }
}
?>

And I need a way out in this style

    /* Objetivo

    Codigo: XPT001 | Nome: Text Name 01 | Descrição: Text Desc 01
    Codigo: BHTLN | Nome: Text Name 02 | Descrição: Text Desc 02
    ....
    Codigo: XPT002 | Nome: Text Name 008*01 | Descrição: Text Desc 008*01

    */

I don’t know if the preg_match_all is the best way to do it

1 answer

1


For each key starting with "Trophy", simply extract the "name"/"desc" section and the respective code, and then set the values accordingly:

$json = json_decode(file_get_contents("texts.json"));
$result = [];
foreach ($json as $key => $value) {
    if (preg_match("/^trophy_(name|desc)_(.+)/", $key, $match)) {
        $campo = $match[1]; // "name" ou "desc"
        $codigo = $match[2];
        $result[$codigo][$campo] = $value;
    }
}

I used the bookmark ^ which indicates the beginning of the string, so I only get the keys starting with "Trophy". And I used .+ (one or more characters), instead of .* (zero or more characters) to get the code. But if you want, you can be more specific (for example, [A-Z0-9]+ to get uppercase letters or digits), since the dot takes any character.

With this, the array structure $result will be:

array(6) {
  ["XPT001"]=>
  array(2) {
    ["name"]=>
    string(12) "Text Name 01"
    ["desc"]=>
    string(12) "Text Desc 01"
  }
  ["BHTLN"]=>
  array(2) {
    ["name"]=>
    string(12) "Text Name 02"
    ["desc"]=>
    string(12) "Text Desc 02"
  }
  etc...

That is, each code points to an array containing the keys "name" and "desc", and their respective values.

Once you have this array, just scroll through it to print the data the way you want. Ex:

foreach($result as $code => $vals) {
    echo "Código: {$code} | Nome: {$vals['name']} | Descrição: {$vals['desc']}\n";
}

Exit:

Código: XPT001 | Nome: Text Name 01 | Descrição: Text Desc 01
Código: BHTLN | Nome: Text Name 02 | Descrição: Text Desc 02
Código: XPT020 | Nome: Text Name 03 | Descrição: Text Desc 03
Código: OPB852 | Nome: Text Name 04 | Descrição: Text Desc 04
Código: XPTHJN | Nome: Text Name 06 | Descrição: Text Desc 06
Código: XPT002 | Nome: Text Name 008*01 | Descrição: Text Desc 008*01

Instead of regex, you can also check that the string starts with "Trophy" (just use strpos and see if the position is zero) and use explode to break up the parts:

$json = json_decode(file_get_contents("texts.json"));
$result = [];
foreach ($json as $key => $value) {
    if (strpos($key, 'trophy') === 0) { // se começa com "trophy"
        list($_, $campo, $codigo) = explode('_', $key);
        $result[$codigo][$campo] = $value;
    }
}

And from PHP 8, you can use str_starts_with in place of strpos:

$json = json_decode(file_get_contents("texts.json"));
$result = [];
foreach ($json as $key => $value) {
    if (str_starts_with($key, 'trophy')) { // se começa com "trophy"
        list($_, $campo, $codigo) = explode('_', $key);
        $result[$codigo][$campo] = $value;
    }
}
  • Perfect, thank you very much!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.