Dans ce bref billet, nous allons voir quelques méthodes pour bien utiliser et sauvegarder vos fichiers JSON en PHP.

C’est quoi JSON ?

JSON pour JavaScript Object Notation est un format léger d’échange de données, plus ou moins facile à lire pour les humains mais aisément analysable par une machine. Il a l’avantage de pouvoir être utilisé sous de nombreux langages, comme C, Perl, Python mais surtout PHP et Javascript.

Autrement dit, c’est un format textuel qui permet, comme XML ou Yaml , de stocker et d’échanger des informations, notamment avec Javascript.

Ça donne quoi ?

Voilà à quoi ressemble le contenu d’un fichier ou d’une donnée JSON :

{
    "articles": {
        "1": {
            "title": "Premier article",
            "id": 1
        },
        "2": {
            "title": "Second article",
            "id": 2
        }
    },
    "version": 1.5
}

Il s’agit ici d’un exemple très simple, où articles est un tableau qui contient 2 éléments, qui ont respectivement un titre et un id, et version contient une simple valeur.

Voyons à présent comment exploiter ces données.

L’exploitation

En PHP, il existe une fonction qui permet de décoder un tel objet : json_decode().
Voilà un exemple d’utilisation :

$json = json_decode($jsondata);

Mais il y a 2 façons de l’utiliser.

Comme un tableau

Tout d’abord, la façon la plus simple est de récupérer toutes les informations sous forme d’un tableau. Pour cela, il suffit d’ajouter le paramètre true à la fonction :

$json = json_decode($jsondata, true);

Pour la suite, nous considérerons que la variable $jsondata contient les données JSON du premier code de cet article.

Voyons le résultat que cela produit :

var_dump(json_decode($jsondata, true));

array(2) { 
    ["articles"]=> array(2) { 
        [1]=> array(2) { 
            ["title"]=> string(15) "Premier article" 
            ["id"]=> int(1) } 
        [2]=> array(2) { 
            ["title"]=> string(14) "Second article" 
            ["id"]=> int(2) } 
        } 
    ["version"]=> float(1.5) }

Ici, nous récupérons un simple tableau avec tous les attributs du JSON, que nous pouvons donc exploiter comme un array classique.

Pour accéder au titre du second article, il nous suffira donc de faire :

$json = json_decode($jsondata, true);

echo $json['articles'][2]['title'];
// Second article

Des objets partout

Ensuite, il existe une seconde manière d’utiliser une donnée JSON, avec les objets. Pour cela, ôtons simplement le paramètre true de la fonction json_decode() :

$json = json_decode($jsondata);
var_dump($json);

object(stdClass)#4 (2) { 
    ["articles"]=> object(stdClass)#2 (2) { 
        ["1"]=> object(stdClass)#1 (2) { 
            ["title"]=> string(15) "Premier article" 
            ["id"]=> int(1) } 
        ["2"]=> object(stdClass)#3 (2) { 
            ["title"]=> string(14) "Second article" 
            ["id"]=> int(2) } 
            } 
    ["version"]=> float(1.5) }

Dans ce cas de figure, on voit que tous les éléments sont des objets, et plus précisément de la classe stdClass (pour Standard Class, la classe passe partout de PHP), et les valeurs finales comme title ou version sont des attributs de ces objets.

On peut alors utiliser notre JSON comme un seul objet qui en contiendrait d’autres.
Pour récupérer une information, on peut donc faire :

$json = json_decode($jsondata);
echo $json->{'articles'}->{'2'}->{'title'};
// Second article

Ou encore :

$json = json_decode($jsondata);

foreach ($json->{'articles'} as $article)
{
    echo $article->{'title'} . ' a pour ID : ' . $article->{'id'} . "<br/>";
}
// Premier article a pour ID : 1
// Second article a pour ID : 2

Exportez vos données

A présent, nous allons nous intéresser à l’encodage de vos données en JSON. Comme tout à l’heure, PHP fournit une fonction simple pour cela : json_encode() :

$data = [
    'articles' => [
        1 => [
            'title' => 'Premier article',
            'id' => 1
        ],
        2 => [
            'title' => 'Second article',
            'id' => 2
        ]
    ],
    'version' => 1.5
];

$json = json_encode($data, JSON_PRETTY_PRINT);
echo $json;

{
    "articles": {
        "1": {
            "title": "Premier article",
            "id": 1
        },
        "2": {
            "title": "Second article",
            "id": 2
        }
    },
    "version": 1.5
}

On retrouve finalement notre JSON d’origine. Notez que j’ai utilisé le paramètre JSON_PRETTY_PRINT dans la fonction json_encode() afin de récupérer un format JSON avec une indentation dans un soucis de lisibilité.

Encoder des objets

Ce format nous permet également d’encoder des objets. Voyons cela tout de suite :

$article1 = new Article();
$article1->id = 1;
$article1->title = 'Premier article';

$article2 = new Article();
$article2->id = 2;
$article2->title = 'Second article';

$data = [$article1, $article2];
$json = json_encode($data, JSON_PRETTY_PRINT);

echo $json;

[
    {
        "id": 1,
        "title": "Premier article"
    },
    {
        "id": 2,
        "title": "Second article"
    }
]

Dans ce cas de figure, j’ai créé 2 instances de la classe Article puis leur ai affecté respectivement un title et un id. Pour l’encodage, il suffit de les mettre dans un array et le tour est joué 😉

Pour aller plus loin avec les objets

Il faut que je vous explique quelque chose tout de même concernant l’encodage des objets.

Lorsqu’on transforme un objet au format JSON, tous ses attributs déclarés publiques sont alors passés dans le format. En revanche, tous ses attributs privés et protégés ne le sont pas.

J’ai créé une classe Article comme suit :

class Article
{
    private $id;
    
    protected $url;
    
    public $title;
    
    public function setId($id)
    {
        $this->id = $id;
    }
    
    public function setUrl($url)
    {
        $this->url = $url;
    }
    
    public function setTitle($title)
    {
        $this->title = $title;
    }
}

Notez bien que tous les attributs ne sont pas publics.
Aussi, si j’essaye d’exporter une instance de ma classe, voici le résultat :

$article = new Article();
$article->setId(1);
$article->setUrl('http://test.com');
$article->setTitle('Premier article');

$json = json_encode($article, JSON_PRETTY_PRINT);

echo $json;
{
    "title": "Premier article"
}

Et oui, seul le titre déclaré public sera envoyé au JSON. Pratique ou pas, voyons comment outrepasser cette restriction.

La méthode jsonSerialize()

Depuis PHP 5.4, il est possible d’implémenter une méthode dans la classe d’un objet afin de définir le comportement du dit objet lorsqu’il sera sérialisé. Cette méthode doit se nommer jsonSerialize().
De plus, la classe doit implémenter l’interface JsonSerializable.

Reprenons le code de notre classe Article et implémentons cette méthode :

class Article implements JsonSerializable
{
    private $id;
    
    protected $url;
    
    public $title;
    
    public function setId($id)
    {
        $this->id = $id;
    }
    
    public function setUrl($url)
    {
        $this->url = $url;
    }
    
    public function setTitle($title)
    {
        $this->title = $title;
    }
    
    public function jsonSerialize() {
        return [
            'id' => $this->id,
            'title' => $this->title
        ];
    }
}

Puis retestons notre code :

$article = new Article();
$article->setId(1);
$article->setUrl('http://test.com');
$article->setTitle('Premier article');

$json = json_encode($article, JSON_PRETTY_PRINT);

echo $json;
{
    "id": 1,
    "title": "Premier article"
}

N’est-ce pas magique ? 😉

Un petit mot avant de partir ?

J’espère que vous avez pu voir que JSON est un format vraiment simple à mettre en place et à utiliser. De plus, sa syntaxe non verbeuse fait de lui un format léger et facilement lisible.
Alors, allez-vous franchir le pas et abandonner vos XML ? 😉