Cum verifici daca ceea ce primesti este JSON ?

Salutare !

La serviciu implementez un api in php :slight_smile:

Una din cerinte este sa verific daca ceea ce primesc este JSON. Desi se poate folosi json_last_error () pt acest lucru, problema este ca acesta functie este disponibila cu versiunea de php >= 5.3, iar versiunea de pe server este 5.2.5

Am gasit urmatoarea alternativa(workaround):

$data = file_get_contents(php://input); //citesc ceea ce primesc
$json = json_encode($data);

if(gettype($json) == "object")
{
   echo "este json"
}

Se poate face mai “frumos” decat ce am facut eu si sa merga pe versiunea veche de php ?

Precizare: Stiu structura json-ului. Acel json este trimis de o alta aplicatie. Nu pot face nimic asupra versiunii de php


Pus in #workflow:code-review ca analizam cod ! :smiley:

json_encode($var) == false.

din manual:

Valorile întoarse
Întoarce un șir (string) reprezentat JSON în caz de succes, sau FALSE în cazul eșecului.

edit
din graba m-am gandit la encode.
pentru decode intoarce null in caz de esec

Valorile întoarse ¶
Întoarce valoarea codificată în json cu tipul PHP corespunzător. Valorile true, false și null sunt întoarse ca TRUE, FALSE și NULL respectiv. NULL este întors dacă parametrul json nu poate fi decodificat sau dacă datele pentru codificare sunt mai adânci decât limita de imbricare.

2 Likes

Acum 5 secunde am inchis pagina cu manual !

Merci @alescx ! :smiley:

PHP >= 5.2 && PHP < 5.3.0

$result = json_decode($json);
if ($result === null) {
    // JSON is invalid
}

sau

function isJSON($string){
   return is_string($string) && is_array(json_decode($string, true)) ? true : false;
}
1 Like

vezi ca ai o mica eroare in exemplul ala. trebuie sa folosesti decode, nu encode.

1 Like

@alescx si @zshare merci pt sugestii ! :smiley:

@zshare, a doua varianta a ta, am mai vazut-o sub urmatoarea forma !

function isJson($string) {
    return ((is_string($string) &&
            (is_object(json_decode($string)) ||
            is_array(json_decode($string))))) ? true : false;
}

De aici

Vad ca sunt mai multe idei !

care-i logica la metoda aia? decodezi un json (chiar de 2 ori), vezi daca ai eroare, intorci true sau false si dupa aia il mai decodezi odata? nu inteleg…

1 Like

$data = file_get_contents(php://input);
citeste intr-un string ceea ce primeste

file_get_contents — Reads entire file into a string

$json = json_encode($data);
Encodez ceea ce citesc sub forma de json.

Eu va trebui sa extrag din ceea ce primesc informatii. Sub forma de string este dificil.

pai encode iti transforma ceva (nu conteaza ce) in json. tu nu primesti deja un json acolo?
eu inteleg ca primesti deja un string (json-ul este un string) si vrei sa-l transformi in ceva cu care sa poti lucra. cum ar fi un array sau un obiect.

1 Like

Nu prea am inteles, prima data spui ca vrei sa verifici daca primesti JSON. Pai de ce faci encode ?
Trebuie sa faci decode.

{
    "GlossEntry": {
        "ID": "SGML",
		"SortAs": "SGML",
		"GlossTerm": "Standard Generalized Markup Language",
		"Acronym": "SGML",
		"Abbrev": "ISO 8879:1986",
		"GlossDef": {
            "para": "A meta-markup language, used to create markup languages such as DocBook.",
			"GlossSeeAlso": ["GML", "XML"]
        },
		"GlossSee": "markup"
    }
}
$json = file_get_contents('test.json');
$result = json_decode($json);

if ($result === null) return false;

echo $result->GlossEntry->ID; // SGML
2 Likes

Gata, am inteles !!

Merci pt clarificare !

Ma asteptam ca vine sub foma urmatoare

“{
“GlossEntry”: {
“ID”: “SGML”,
“SortAs”: “SGML”,
“GlossTerm”: “Standard Generalized Markup Language”,
“Acronym”: “SGML”,
“Abbrev”: “ISO 8879:1986”,
“GlossDef”: {
“para”: “A meta-markup language, used to create markup languages such as DocBook.”,
“GlossSeeAlso”: [“GML”, “XML”]
},
“GlossSee”: “markup”
}
}”

Am facut un mic test si intr-adevar, aveti dreptate. Nu este nevoie de encode.

PS: Mai greu dupa cateva beri !
Voi corecta in cod, maine, la serviciu

Merci inca o data ! :smiley:

LE:
M-am incurcat in functii :facepalm:

Pe server am folosit json_decode()

1 Like

my 2 cents:

  • Când implementezi un API nu mi se pare logic să “ghicești” ce fel de date primești pe baza inputului primit. De obicei modul de encodare a datelor îl determini folosind una din metodele de mai jos:
    • trimițând un HTTP header când faci requestul (clientul API-ului) - considerat best practice din ce am văzut eu până acum. Exemplu: Accept: application/json sau Accept: application/xml
    • cu un parametru GET. Exemplu: /api/endpoint?type=json sau /api/endpoint?type=xml
    • folosind un URL diferit pentru fiecare type. Exemplu: /api/endpoint.json sau /api/endpoint.xml
  • Exemplele de cod prezentate mai sus au două inconveniente: nu acceptă null ca și JSON valid și dacă le folosești așa o să faci json_encode() de două ori (folosești memorie și putere de procesare aiurea).

Eu aș implementa ceva de genul codului de mai jos, care acoperă și cazul cu JSONul valid null și eviți să apelezi json_decode() de două ori (odată pentru validare și a doua oară ca să extragi datele).

function decode_input_json($input) {
  $output = NULL;
  if (is_string($input)) {
    $output = json_decode($input);
  }
  if ($output === NULL && $input !== "null") {
     throw new Exception("Invalid input JSON.");
  }
  return $output;
}

// Și când vrei să validezi și să extragi informațiile transmise:
try {
  $input = decode_input_json($input);
}
catch(Exception $e) {
  $input = FALSE; // Sau orice altă logică vrei să folosești când $input e invalid
}
4 Likes

Mic follow up:

Am pornit de la stadiul de experinment facut la ora 17. Initial erau pana in 10 linii de cod. Am trecut ziua urmatoare la if else - uri.

Lunea trecuta am integrat sugestia lui @Luxian si am trecut la un refactor de cod.

Am mutat logica api-ului intr-o clasa pe care am numit-o ApiOps si in ea am adaugat metodele corespunzatoare. In fisierul de index am daugat un switch case pt selectarea actiunilor. Am adaugat componenta de logging. Pt log am folosit log4php. Am folosit configurarea din exemplele de pe site, nothing fancy.

Pe partea de testare, am folosit Postman.
Experienta de refactoring a fost interesanta si m-a facut sa regandesc anumite lucruri. Pe partea de coding style cred ca am respectat PSR-2. Am zis sa pornesc cu el.

Eu zic ca am facut o treaba buna. Mai am insa mult de lucru !

1 Like