Ir para conteúdo
Fórum Script Brasil
  • 0

Função genérica para atualizar chave em JSON duplicada usando o PHP


Jorge Kania

Pergunta

Tenho a seguinte situação.
Recebo vários JSONs podendo ou não ser multidimensional, preciso atualizar uma determinada chave deste JSON, o problema é que algumas chaves podem ser duplicadas, bem como seus respectivos valores. Como estou tentando criar uma função genérica para navegar em qualquer JSON e modificar a chave em si, com estas duplicidades de chaves, estou tendo dificuldades em dizer ao código qual é chave que devo alterar.

 

Arquivo JSON Exemplo

 

{
      "CREDITOR": {
        "TAX": {
          "TAC": 0.7
        },
        "ENABLE": "true",
        "PRODUCTION": {
          "email": "email@dominio.com",
          "senha": "12457895",
          "BASE_URL": "https://domino.com"
        },
        "HOMOLOGATION": {
          "email": "email@dominio.com",
          "senha": "12457895",
          "BASE_URL": "https://domino.com"
        },
        "TARGET_VALUES": 5000000
      }
    }

 

Converto o JSON para array

 

$json = json_decode($json_string, true);


Função que criei até aqui

 

   

/**
     * Encontra a chave correspondente dentro do JSON
     *
     * @param array $jsonArray - JSON a ser verificado
     * @param string $keyFather - chave de entrada
     * @param string $keyUpdate - chave que modificar
     * @param string $valueUpdate - novo valor da chave
     * @return string
     *
     */
    public static function searchKeyJson(array $jsonArray, string $keyFather, string $keyUpdate = null, $valueUpdate = null)
    {
        foreach ($jsonArray as $key => $value) {
            if ($key == $keyFather && $keyUpdate == null) {
                $jsonArray[$key] =  $valueUpdate;
                return $jsonArray;
            }
            if ($key == $keyFather && $keyUpdate != null) {
                $jsonArray[$keyFather][$keyUpdate] = $valueUpdate;
                return $jsonArray;
            }
            if (is_array($value)) {
                if (($result = self::searchKeyJson($value, $keyFather, $keyUpdate, $valueUpdate)) !== false) {
                    if ($keyUpdate == null) {
                        return $result;
                    } else {
                        return $result;
                    }
                }
            }
        }
        return false;
    }


Até modifico o valor, mais no final para salvar, ele não monta o JSON como original, ele caba ignorando a chave inicial no JSON de exmeplo "CREDITOR": {}

 

Retorno da função (notem que esta forma do padrão da original)

 

=> [
         "TAX" => [
           "TAC" => 0.7,
         ],
         "ENABLE" => "true",
         "PRODUCTION" => [
           "email" => "teste",
           "senha" => "12457895",
           "BASE_URL" => "https://domino.com",
         ],
         "HOMOLOGATION" => [
           "email" => "email@dominio.com",
           "senha" => "12457895",
           "BASE_URL" => "https://domino.com",
         ],
         "TARGET_VALUES" => 5000000,
       ]

 

Se eu percorrer o array e tentar modificar a chave em questão, ele muda todas as as chaves que tiverem no JSON porque tem duplicidade.

Como posso resolver isto com uma função global que sirva para qualquer padrão de JSON que eu tiver?

Link para o comentário
Compartilhar em outros sites

4 respostass a esta questão

Posts Recomendados

  • 0

Boa noite, json não é a minha praia, mesmo assim eu só achei uma chave no exemplo, fiz uma enorme modificação no exemplo, e consegui um monte de chaves. Veja só:

<?php
$exemplo='{"CREDITOR": {"TAX": {"TAC": 0.7},"ENABLE": "true","PRODUCTION": {"email": "email@dominio.com","senha": "12457895",
          "BASE_URL": "https://domino.com"}, "HOMOLOGATION": {"email": "email@dominio.com","senha": "12457895","BASE_URL": 		"https://domino.com"},
"TARGET_VALUES": 5000000}}';
$json=json_decode($exemplo);
foreach($json as $key=>$value){var_dump($key);}
// resultado: C:\wamp64\www\frank\astudy.php:6:string 'CREDITOR' (length=8)

$exemplo2='{"CREDITOR": {"TAX": {"TAC": 0.7}},"ENABLE": "true","PRODUCTION": {"email": "email@dominio.com","senha": "12457895",
          "BASE_URL": "https://domino.com"}, "HOMOLOGATION": {"email": "email@dominio.com","senha": "12457895","BASE_URL": "https://domino.com"},
"TARGET_VALUES": 5000000}';
$json=json_decode($exemplo2);
foreach($json as $key=>$value){var_dump($key);}
// resultado:
//C:\wamp64\www\frank\astudy.php:13:string 'CREDITOR' (length=8)
//C:\wamp64\www\frank\astudy.php:13:string 'ENABLE' (length=6)
//C:\wamp64\www\frank\astudy.php:13:string 'PRODUCTION' (length=10)
//C:\wamp64\www\frank\astudy.php:13:string 'HOMOLOGATION' (length=12)
//C:\wamp64\www\frank\astudy.php:13:string 'TARGET_VALUES' (length=13)

Por outro lado, se o primeiro exemplo estiver certo, tendo somente uma chave, eu fiz essa gambiarra para conseguir as subchaves:

 

<?php
$exemplo='{"CREDITOR": {"TAX": {"TAC": 0.7},"ENABLE": "true","PRODUCTION": {"email": "email@dominio.com","senha": "12457895",
          "BASE_URL": "https://domino.com"}, "HOMOLOGATION": {"email": "email@dominio.com","senha": "12457895","BASE_URL": "https://domino.com"},
"TARGET_VALUES": 5000000}}';
$json=json_decode($exemplo);
foreach($json as $key=>$value){var_dump($key);
	foreach($value as $subkey=>$subvalue){var_dump($subkey);}}
//resultado:
//C:\wamp64\www\frank\astudy.php:6:string 'CREDITOR' (length=8)
//C:\wamp64\www\frank\astudy.php:7:string 'TAX' (length=3)
//C:\wamp64\www\frank\astudy.php:7:string 'ENABLE' (length=6)
//C:\wamp64\www\frank\astudy.php:7:string 'PRODUCTION' (length=10)
//C:\wamp64\www\frank\astudy.php:7:string 'HOMOLOGATION' (length=12)
//C:\wamp64\www\frank\astudy.php:7:string 'TARGET_VALUES' (length=13)

Essa é uma gambiarra bem particular, ele só funciona para o json que tiver apenas uma chave e o valor correspondente é um json embutido com outras chaves. A minha sugestão é você adaptar o seu código somente às subchaves.

Editado por Frank K Hosaka
Link para o comentário
Compartilhar em outros sites

  • 1

Olá noite Frank, obrigado por responder.

Vamos lá, vou detalhar melhor o que estou tentando fazer.

 

A aplicação Backend esta em uma API em Laravel 9, com banco de dados Mysql e o Front em Vue.js 3.

No banco de dados, existem várias tabelas com colunas do tipo jsonb.

O que preciso fazer é manipular este campo jsonb no PHP, para isto pensei no seguinte.

 

- Ter uma função genérica já que estes campos jsonb não tem um json igual em cada;

- A função precisa poder percorrer o json (já convertido em array para trabalhar no php) e encontrara chave especifica para poder modifica-la

 

No exemplo acima, eu cheguei a conseguir modificar a chave email da chave pai PRODUCTION efetuando chamada

searchKeyJson($jsonArray, , , "VALOR MODIFICADO")

Sendo que o parâmetro $keyUpdate é facultativo, já que posso precisar alterar um chave que esta em primeiro nível no json.

 

Funcionou a modificação para este exemplo de json/array, mais não funciona em todos os casos, pois como monto as chaves na $jsonArray[$keyFather][$keyUpdate] = $valueUpdate; ele se perde quando não encontra as referencias conforme a profundidade do array.


A ideia inicial era que eu pudesse passar apenas a chave em si que quero manipular (exemplo: email), mais não funcionaria porque como no json do exemplo, eu tenho duas chaves e-mail, uma no PRODUCTION e outra no HOMOLOGATION, logo ou vai modificar todas as chaves, ou vai modificar apenas a primeira que encontrar.

 

Ai estou pesquisando para ver como posso resolver este pepinão (hehehe), tendo em vista que estes campos jsonb do banco tem configuração do sistema importantes que precisam ser manipulados em um front, não da para ficar ajustando eles não mão sempre que precisar.

Link para o comentário
Compartilhar em outros sites

  • 0

Ok, entendi. Eu ainda não sei o que é front-back end e nem tampouco json. Eu só tenho um notebook e um celular, mas como tenho tempo de sobra, posso começar o meu projeto de modificar um json. Vou começar com {"nome":"frank"}, depois com {"nome":"frank","nome:"joão"}, depois com {"canalhas":{"nome":"frank,"nome":"joão"}}.

Como não conheço nada de json, vou ter que estudar se é possível 

1) o PHP identificar um json de verdade de um fajuto

2) o PHP quantificar quantos json tem um json

3) o PHP tabular a chave e o valor

4) se o valor for outro json, ele tabular novamente

5) do lado de cada valor vou colocar um input (para evitar o efeito post, vou dar um jeito do input focar outro input, quando o usuário apertar {ENTER})

6) finalmente sincronizar todos os inputs com os respectivos valores.

Boa sorte para nos dois.

Link para o comentário
Compartilhar em outros sites

  • 0

Depois de várias tentativas, eu acabei desistindo. O json não é nada fácil.

Para não abandonar você, a minha sugestão é fazer uma boa gambiarra, não trabalhar com o json, e alterar o texto assim:

<style>form{margin: 0}</style>
<?php
session_start();
function str_replace_first($from, $to, $subject){
    $from = '/'.preg_quote($from, '/').'/'; return preg_replace($from, $to, $subject, 1); }
if (!isset($_POST['novo'])){
  $_SESSION['json']='{"CREDITOR": {"TAX": {"TAC": 0.7},"ENABLE": "true","PRODUCTION": {"email": "email@dominio.com","senha": "12457895",
          "BASE_URL": "https://domino.com"}, "HOMOLOGATION": {"email": "email@dominio.com","senha": "12457895","BASE_URL": 		"https://domino.com"},
"TARGET_VALUES": 5000000}}';}
if (isset($_POST['novo'])){
	$antigo=$_POST['antigo'];
	$novo=$_POST['novo'];
	$texto=$_SESSION['json'];
	$novotexto=str_replace_first($antigo,$novo,$texto);
	$_SESSION['json']=$novotexto;}
echo $_SESSION['json'];
echo "<table><tr height=100px><td>";
echo "<form method=post>O que você quer mudar?<td><input name=antigo>";
echo "<tr><td>Para?<td><input name=novo onchange=submit()></form></td>";

Caso você queira substituir os dois emails ao mesmo tempo, mude a função str_replace_first por str_replace.

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,3k
×
×
  • Criar Novo...