Szukaj…


Wprowadzenie

JSON ( JavaScript Object Notation ) to niezależny od platformy i języka sposób serializacji obiektów na zwykły tekst. Ponieważ jest często używany w Internecie, podobnie jak PHP, istnieje podstawowe rozszerzenie do pracy z JSON w PHP.

Składnia

  • ciąg json_encode (mieszana $ wartość [, int $ opcje = 0 [, int $ głębokość = 512]])
  • mixed json_decode (ciąg $ json [, bool $ assoc = false [, int $ depth = 512 [, int $ options = 0]]])

Parametry

Parametr Detale
json_encode -
wartość Wartość jest kodowana. Może być dowolnego typu oprócz zasobu. Wszystkie dane ciągu muszą być zakodowane w UTF-8.
opcje Maska bitów składająca się z JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT, JSON_ZER_PRES_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESS_PRESSIONE. Zachowanie tych stałych jest opisane na stronie stałych JSON .
głębokość Ustaw maksymalną głębokość. Musi być większy niż zero.
json_decode -
json Ciąg json jest dekodowany. Ta funkcja działa tylko z łańcuchami zakodowanymi w UTF-8.
doc Powinna funkcja zwracać tablicę asocjacyjną zamiast obiektów.
opcje Maska bitowa opcji dekodowania JSON. Obecnie obsługiwany jest tylko JSON_BIGINT_AS_STRING (domyślnie rzutuje duże liczby całkowite jako liczby zmiennoprzecinkowe)

Uwagi

  • Obsługa nieprawidłowego JSON przez json_decode jest bardzo niestabilna i bardzo trudno jest wiarygodnie ustalić, czy dekodowanie się powiodło, json_decode zwraca wartość null dla niepoprawnego wejścia, mimo że null jest również doskonale poprawnym obiektem do dekodowania przez JSON. Aby zapobiec takim problemom, zawsze powinieneś wywoływać json_last_error za każdym razem, gdy go używasz.

Dekodowanie ciągu JSON

Funkcja json_decode() przyjmuje jako pierwszy parametr ciąg zakodowany w JSON i analizuje go w zmiennej PHP.

Zwykle json_decode() zwróci obiekt \ stdClass, jeśli elementem najwyższego poziomu w obiekcie JSON jest słownik lub tablica indeksowana, jeśli obiekt JSON jest tablicą. Zwróci również wartości skalarne lub NULL dla niektórych wartości skalarnych, takich jak proste łańcuchy, "true" , "false" i "null" . Zwraca również NULL dla każdego błędu.

// Returns an object (The top level item in the JSON string is a JSON dictionary)
$json_string = '{"name": "Jeff", "age": 20, "active": true, "colors": ["red", "blue"]}';
$object = json_decode($json_string);
printf('Hello %s, You are %s years old.', $object->name, $object->age);
#> Hello Jeff, You are 20 years old.

// Returns an array (The top level item in the JSON string is a JSON array)
$json_string = '["Jeff", 20, true, ["red", "blue"]]';
$array = json_decode($json_string);
printf('Hello %s, You are %s years old.', $array[0], $array[1]);

Użyj var_dump() aby wyświetlić typy i wartości każdej właściwości w obiekcie, który zdekodowaliśmy powyżej.

// Dump our above $object to view how it was decoded
var_dump($object);

Dane wyjściowe (zwróć uwagę na typy zmiennych):

class stdClass#2 (4) {
 ["name"] => string(4) "Jeff"
 ["age"] => int(20)
 ["active"] => bool(true)
 ["colors"] =>
   array(2) {
     [0] => string(3) "red"
     [1] => string(4) "blue"
   }
}

Uwaga: Typy zmiennych w JSON zostały przekonwertowane na ich odpowiedniki PHP.


Aby zwrócić tablicę asocjacyjną dla obiektów JSON zamiast zwracać obiekt, przekaż true jako drugi parametr do json_decode() .

$json_string = '{"name": "Jeff", "age": 20, "active": true, "colors": ["red", "blue"]}';
$array = json_decode($json_string, true); // Note the second parameter
var_dump($array);

Dane wyjściowe (zwróć uwagę na strukturę asocjacyjną tablicy):

array(4) {
  ["name"] => string(4) "Jeff"
  ["age"] => int(20)
  ["active"] => bool(true)
  ["colors"] =>
  array(2) {
    [0] => string(3) "red"
    [1] => string(4) "blue"
  }
}

Drugi parametr ( $assoc ) nie działa, jeśli zwracana zmienna nie jest obiektem.

Uwaga: Jeśli $assoc parametru $assoc , utracisz rozróżnienie między pustą tablicą a pustym obiektem. Oznacza to, że ponowne uruchomienie json_encode() na zdekodowanym wyjściu spowoduje inną strukturę JSON.

Jeśli ciąg JSON ma „głębokość” większą niż 512 elementów ( 20 elementów w wersjach starszych niż 5.2.3 lub 128 w wersji 5.2.3 ) w rekurencji, funkcja json_decode() zwraca NULL . W wersjach 5.3 lub nowszych limit ten można kontrolować za pomocą trzeciego parametru ( $depth ), jak omówiono poniżej.


Zgodnie z instrukcją:

PHP implementuje nadzbiór JSON, jak określono w oryginalnym »RFC 4627 - będzie także kodować i dekodować typy skalarne i NULL. RFC 4627 obsługuje te wartości tylko wtedy, gdy są zagnieżdżone w tablicy lub obiekcie. Chociaż ten nadzbiór jest zgodny z rozszerzoną definicją „tekstu JSON” w nowszej wersji »RFC 7159 (która ma zastąpić RFC 4627) i » ECMA-404 , może to powodować problemy z interoperacyjnością ze starszymi parserami JSON, które ściśle przestrzegają RFC 4627, gdy kodowanie pojedynczej wartości skalarnej.

Oznacza to, że na przykład prosty ciąg zostanie uznany za prawidłowy obiekt JSON w PHP:

$json = json_decode('"some string"', true);
var_dump($json, json_last_error_msg());

Wynik:

string(11) "some string"
string(8) "No error"

Ale proste łańcuchy, nie w tablicy ani w obiekcie, nie są częścią standardu RFC 4627 . W rezultacie takie narzędzia do sprawdzania online, jak JSLint , JSON Formatter & Validator (w trybie RFC 4627) spowodują błąd.

Istnieje trzeci parametr $depth dla głębokości rekurencji (wartość domyślna to 512 ), co oznacza ilość zagnieżdżonych obiektów wewnątrz oryginalnego obiektu do odkodowania.

Istnieje czwarty parametr $options . Obecnie akceptuje tylko jedną wartość, JSON_BIGINT_AS_STRING . Domyślne zachowanie (które wyłącza tę opcję) polega na rzucaniu dużych liczb całkowitych na liczby zmiennoprzecinkowe zamiast łańcuchów.

Nieprawidłowe, nie zapisane małymi literami warianty literału true, false i null nie są już akceptowane jako prawidłowe dane wejściowe.

Więc ten przykład:

var_dump(json_decode('tRue'), json_last_error_msg());
var_dump(json_decode('tRUe'), json_last_error_msg());
var_dump(json_decode('tRUE'), json_last_error_msg());
var_dump(json_decode('TRUe'), json_last_error_msg());
var_dump(json_decode('TRUE'), json_last_error_msg());
var_dump(json_decode('true'), json_last_error_msg());

Przed PHP 5.6:

bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"
bool(true)
string(8) "No error"

I po:

NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
NULL
string(12) "Syntax error"
bool(true)
string(8) "No error"

Podobne zachowanie występuje w przypadku wartości false i null .

Zauważ, że json_decode() zwróci NULL jeśli ciąg nie może zostać przekonwertowany.

$json = "{'name': 'Jeff', 'age': 20 }" ;  // invalid json 

$person = json_decode($json);
echo $person->name;    //  Notice: Trying to get property of non-object: returns null
echo json_last_error();     
#  4 (JSON_ERROR_SYNTAX)
echo json_last_error_msg(); 
#  unexpected character 

Nie jest bezpiecznie polegać wyłącznie na wartości NULL zwracanej w celu wykrycia błędów. Na przykład, jeśli ciąg JSON nie zawiera nic oprócz "null" , json_decode() zwróci null , mimo że nie wystąpił błąd.

Kodowanie ciągu JSON

Funkcja json_encode przekształci tablicę PHP (lub, od PHP 5.4, obiekt, który implementuje interfejs JsonSerializable ) na ciąg zakodowany w JSON. Zwraca ciąg zakodowany w JSON w przypadku sukcesu lub FALSE w przypadku niepowodzenia.

$array = [
    'name' => 'Jeff',
    'age' => 20,
    'active' => true,
    'colors' => ['red', 'blue'],
    'values' => [0=>'foo', 3=>'bar'],
];

Podczas kodowania ciąg typów danych PHP, liczba całkowita i wartość logiczna są konwertowane na ich odpowiednik JSON. Tablice asocjacyjne są kodowane jako obiekty JSON, a - gdy są wywoływane z domyślnymi argumentami - tablice indeksowane są kodowane jako tablice JSON. (Chyba że klucze tablicy nie są ciągłą sekwencją numeryczną rozpoczynającą się od 0, w którym to przypadku tablica zostanie zakodowana jako obiekt JSON.)

echo json_encode($array);

Wynik:

{"name":"Jeff","age":20,"active":true,"colors":["red","blue"],"values":{"0":"foo","3":"bar"}}

Argumenty

Od PHP 5.3 drugim argumentem do json_encode jest json_encode bitowa, która może być jedną lub więcej z poniższych.

Podobnie jak w przypadku każdej maski bitowej, można je łączyć z binarnym operatorem OR | .

PHP 5.x 5.3

JSON_FORCE_OBJECT

Wymusza utworzenie obiektu zamiast tablicy

$array = ['Joel', 23, true, ['red', 'blue']];
echo json_encode($array);
echo json_encode($array, JSON_FORCE_OBJECT);

Wynik:

["Joel",23,true,["red","blue"]]
{"0":"Joel","1":23,"2":true,"3":{"0":"red","1":"blue"}}

JSON_HEX_TAG , JSON_HEX_AMP , JSON_HEX_APOS , JSON_HEX_QUOT

Zapewnia następujące konwersje podczas kodowania:

Stały Wejście Wynik
JSON_HEX_TAG < \u003C
JSON_HEX_TAG > \u003E
JSON_HEX_AMP & \u0026
JSON_HEX_APOS ' \u0027
JSON_HEX_QUOT " \u0022
$array = ["tag"=>"<>", "amp"=>"&", "apos"=>"'", "quot"=>"\""];
echo json_encode($array);
echo json_encode($array, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);

Wynik:

{"tag":"<>","amp":"&","apos":"'","quot":"\""}
{"tag":"\u003C\u003E","amp":"\u0026","apos":"\u0027","quot":"\u0022"}
PHP 5.x 5.3

JSON_NUMERIC_CHECK

Zapewnia, że ciągi liczbowe są konwertowane na liczby całkowite.

$array = ['23452', 23452];
echo json_encode($array);
echo json_encode($array, JSON_NUMERIC_CHECK);

Wynik:

["23452",23452]    
[23452,23452]
PHP 5.x 5.4

JSON_PRETTY_PRINT

Sprawia, że JSON jest łatwo czytelny

$array = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4];
echo json_encode($array);
echo json_encode($array, JSON_PRETTY_PRINT);

Wynik:

{"a":1,"b":2,"c":3,"d":4}
{
    "a": 1,
    "b": 2,
    "c": 3,
    "d": 4
}

JSON_UNESCAPED_SLASHES

Obejmuje ukośniki nieokreślone / przodu na wyjściu

$array = ['filename' => 'example.txt', 'path' => '/full/path/to/file/'];
echo json_encode($array);
echo json_encode($array, JSON_UNESCAPED_SLASHES);

Wynik:

{"filename":"example.txt","path":"\/full\/path\/to\/file"}
{"filename":"example.txt","path":"/full/path/to/file"}

JSON_UNESCAPED_UNICODE

Zawiera w kodzie wyjściowym znaki zakodowane w UTF8 zamiast ciągów zakodowanych w formacie \u

$blues = ["english"=>"blue", "norwegian"=>"blå", "german"=>"blau"];
echo json_encode($blues);
echo json_encode($blues, JSON_UNESCAPED_UNICODE);

Wynik:

{"english":"blue","norwegian":"bl\u00e5","german":"blau"}
{"english":"blue","norwegian":"blå","german":"blau"}
PHP 5.x 5.5

JSON_PARTIAL_OUTPUT_ON_ERROR

Zezwala na kontynuowanie kodowania, jeśli napotkane zostaną pewne wartości niekodowalne.

$fp = fopen("foo.txt", "r");
$array = ["file"=>$fp, "name"=>"foo.txt"];
echo json_encode($array); // no output
echo json_encode($array, JSON_PARTIAL_OUTPUT_ON_ERROR);

Wynik:

{"file":null,"name":"foo.txt"}
PHP 5.x 5.6

JSON_PRESERVE_ZERO_FRACTION

Zapewnia, że zmiennoprzecinkowe są zawsze kodowane jako zmiennoprzecinkowe.

$array = [5.0, 5.5];
echo json_encode($array);
echo json_encode($array, JSON_PRESERVE_ZERO_FRACTION);

Wynik:

[5,5.5]
[5.0,5.5]
PHP 7.x 7.1

JSON_UNESCAPED_LINE_TERMINATORS

W połączeniu z JSON_UNESCAPED_UNICODE zachowanie starszych wersji PHP i nie ucieka przed znakami U + 2028 LINE SEPARATOR i U + 2029 SEPARATOR PARAGRAPH. Chociaż są one poprawne w JSON, te znaki nie są poprawne w JavaScript, więc domyślne zachowanie JSON_UNESCAPED_UNICODE zostało zmienione w wersji 7.1.

$array = ["line"=>"\xe2\x80\xa8", "paragraph"=>"\xe2\x80\xa9"];
echo json_encode($array, JSON_UNESCAPED_UNICODE);
echo json_encode($array, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS);

Wynik:

{"line":"\u2028","paragraph":"\u2029"}
{"line":"
","paragraph":"
"}

Debugowanie błędów JSON

Kiedy json_encode lub json_decode nie trafia do analizowania ciąg dostarczone, zwróci false . Sam PHP nie będzie generował żadnych błędów ani ostrzeżeń, gdy to się stanie, na użytkowniku spoczywa obowiązek użycia funkcji json_last_error () i json_last_error_msg () w celu sprawdzenia, czy wystąpił błąd i działania odpowiednio w aplikacji (debuguj go, pokaż komunikat o błędzie itp.).

Poniższy przykład pokazuje typowy błąd podczas pracy z JSON, błąd dekodowania / kodowania łańcucha JSON (na przykład z powodu przekazania nieprawidłowego łańcucha zakodowanego UTF-8) .

// An incorrectly formed JSON string
$jsonString = json_encode("{'Bad JSON':\xB1\x31}");

if (json_last_error() != JSON_ERROR_NONE) {
    printf("JSON Error: %s", json_last_error_msg());
}

#> JSON Error: Malformed UTF-8 characters, possibly incorrectly encoded

json_last_error_msg

json_last_error_msg() zwraca czytelny dla człowieka komunikat o ostatnim błędzie, który wystąpił podczas próby zakodowania / odkodowania łańcucha.

  • Ta funkcja zawsze zwraca ciąg znaków , nawet jeśli nie wystąpił błąd.
    Ciąg domyślny zakaz błędu No Error
  • Zwróci false jeśli wystąpi inny (nieznany) błąd
  • Ostrożnie, gdy używasz tego w pętlach, ponieważ json_last_error_msg zostanie zastąpiony przy każdej iteracji.

Tej funkcji należy używać tylko do otrzymania komunikatu do wyświetlenia, a nie do testowania w instrukcjach sterujących.

// Don't do this:
if (json_last_error_msg()){} // always true (it's a string)
if (json_last_error_msg() != "No Error"){} // Bad practice

// Do this: (test the integer against one of the pre-defined constants)
if (json_last_error() != JSON_ERROR_NONE) {
    // Use json_last_error_msg to display the message only, (not test against it)
    printf("JSON Error: %s", json_last_error_msg());
}

Ta funkcja nie istnieje przed PHP 5.5. Oto implementacja polifill:

if (!function_exists('json_last_error_msg')) {
    function json_last_error_msg() {
        static $ERRORS = array(
            JSON_ERROR_NONE => 'No error',
            JSON_ERROR_DEPTH => 'Maximum stack depth exceeded',
            JSON_ERROR_STATE_MISMATCH => 'State mismatch (invalid or malformed JSON)',
            JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
            JSON_ERROR_SYNTAX => 'Syntax error',
            JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded'
        );

        $error = json_last_error();
        return isset($ERRORS[$error]) ? $ERRORS[$error] : 'Unknown error';
    }
}

json_last_error

json_last_error() zwraca liczbę całkowitą odwzorowaną na jedną ze wstępnie zdefiniowanych stałych dostarczonych przez PHP.

Stały Znaczenie
JSON_ERROR_NONE Nie wystąpił błąd
JSON_ERROR_DEPTH Maksymalna głębokość stosu została przekroczona
JSON_ERROR_STATE_MISMATCH Niepoprawny lub zniekształcony JSON
JSON_ERROR_CTRL_CHAR Błąd znaku kontrolnego, być może niepoprawnie zakodowany
JSON_ERROR_SYNTAX Błąd składniowy (od PHP 5.3.3)
JSON_ERROR_UTF8 Zniekształcone znaki UTF-8, być może niepoprawnie zakodowane (od PHP 5.5.0)
JSON_ERROR_RECURSION Co najmniej jedno odwołanie rekurencyjne w wartości do zakodowania
JSON_ERROR_INF_OR_NAN Jedna lub więcej wartości NAN lub INF w wartości do zakodowania
JSON_ERROR_UNSUPPORTED_TYPE Podano wartość typu, którego nie można zakodować

Korzystanie z JsonSerializable w obiekcie

PHP 5.x 5.4

Podczas tworzenia interfejsów API REST może być konieczne zmniejszenie informacji o obiekcie, który ma zostać przekazany do aplikacji klienckiej. W tym celu w tym przykładzie pokazano, jak korzystać z interfejsu JsonSerialiazble .

W tym przykładzie klasa User faktycznie rozszerza obiekt modelu DB hipotetycznej ORM.

class User extends Model implements JsonSerializable {
    public $id;
    public $name;
    public $surname;
    public $username;
    public $password;
    public $email;
    public $date_created;
    public $date_edit;
    public $role;
    public $status;

    public function jsonSerialize() {
        return [
            'name' => $this->name,
            'surname' => $this->surname,
            'username' => $this->username
        ];
    }
}

Dodaj implementację JsonSerializable do klasy, udostępniając jsonSerialize() .

public function jsonSerialize()

Teraz w twoim kontrolerze aplikacji lub skrypcie, przekazując obiekt User do json_encode() , otrzymasz całą tablicę zakodowaną w json metody jsonSerialize() zamiast całego obiektu.

json_encode($User);

Wróci:

{"name":"John", "surname":"Doe", "username" : "TestJson"}

przykład wartości właściwości.

Zmniejszy to zarówno ilość danych zwracanych z punktu końcowego RESTful, jak i pozwoli wykluczyć właściwości obiektu z reprezentacji json.


Korzystanie z właściwości prywatnych i chronionych za pomocą json_encode()

Aby uniknąć używania JsonSerializable, możliwe jest również użycie właściwości prywatnych lub chronionych w celu ukrycia informacji o klasie przed wyjściem json_encode() . Klasa nie musi zatem implementować \ JsonSerializable.

Funkcja json_encode () będzie kodować tylko publiczne właściwości klasy w JSON.

<?php

class User {
    // private properties only within this class
    private $id;
    private $date_created;
    private $date_edit;

    // properties used in extended classes
    protected $password;
    protected $email;
    protected $role;
    protected $status;

    // share these properties with the end user        
    public $name;
    public $surname;
    public $username;

    // jsonSerialize() not needed here
}        

$theUser = new User();

var_dump(json_encode($theUser));

Wynik:

string(44) "{"name":null,"surname":null,"username":null}"

Nagłówek Json i zwrócona odpowiedź

Dodając nagłówek z typem zawartości jako JSON:

<?php
 $result = array('menu1' => 'home', 'menu2' => 'code php', 'menu3' => 'about');

//return the json response :
header('Content-Type: application/json');  // <-- header declaration
echo json_encode($result, true);    // <--- encode
exit();

Nagłówek jest tam, aby Twoja aplikacja mogła wykryć, które dane zostały zwrócone i jak powinny je obsługiwać.
Uwaga: nagłówek treści to tylko informacja o rodzaju zwracanych danych.

Jeśli używasz UTF-8, możesz użyć:

header("Content-Type: application/json;charset=utf-8");

Przykład jQuery:

$.ajax({
        url:'url_your_page_php_that_return_json'        
    }).done(function(data){
        console.table('json ',data);
        console.log('Menu1 : ', data.menu1);
    });


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow