如何在PHP中解析JSON

2,065 阅读3分钟

JSON是JavaScript Object Notation的缩写,是一种用于存储和交换信息的通用轻量级格式。顾名思义,它最初来源于JavaScript,但它是一种独立于语言的信息存储格式。现在很多语言如PHP都实现了读取和创建JSON数据的功能。

本教程将教你如何在PHP中读取JSON文件并将其转换为一个数组。学习如何使用json_decode()json_encode() 函数来解析JSON。

在PHP中从文件或字符串中读取JSON数据

假设你有一个文件,其中包含JSON格式的信息。你如何在PHP中访问和存储它?

首先,你需要通过使用file_get_contents() 从文件中获取数据到一个变量。一旦数据在一个字符串中,你可以调用 [json_decode()](https://www.php.net/manual/en/function.json-decode.php)函数来提取字符串中的信息。请记住,JSON只是提供了一种使用一组预定义规则将信息存储为字符串的方法。我们的工作是正确解码字符串并获得我们想要的信息。

json_decode() 函数接受四个参数,但在大多数情况下你只需要前两个。第一个参数指定你要解码的字符串。第二个参数决定了解码后的数据是如何返回的。设置为true 将返回一个关联数组,false 将返回对象。下面是一个基本的例子。我们有一个名为people.json的文件,内容如下。

{
    "name": "Monty",
    "email": "monty@something.com",
    "age": 77
}

我们可以通过使用下面的代码从这个JSON文件中读取信息。

<?php

$people_json = file_get_contents('people.json');

$decoded_json = json_decode($people_json, false);

echo $decoded_json->name;
// Monty

echo $decoded_json->email;
// monty@something.com

echo $decoded_json->age;
// 77

?>

在上面的例子中,json_decode() 返回一个对象,因为第二个参数被设置为false 。你可以将其设置为true ,以关联数组的形式获得数据。

<?php

$people_json = file_get_contents('people.json');

$decoded_json = json_decode($people_json, true);

echo $decoded_json['name'];
// Monty

echo $decoded_json['email'];
// monty@something.com

echo $decoded_json['age'];
// 77

?>

现在,我们将解码稍显复杂的JSON,并尝试从中获取有用的信息。

{
    "name": "Monty",
    "email": "monty@something.com",
    "age": 77,
    "countries": [
        {"name": "Spain", "year": 1982},
        {"name": "Australia", "year": 1996},
        {"name": "Germany", "year": 1987}
    ]
}

我们的目标是得到这个人在不同年份访问过的所有国家。$decoded_json['countries'] 返回的值实际上是一个数组,我们将像普通的数组一样通过它来循环获得我们的数据。

<?php

$people_json = file_get_contents('people.json');

$decoded_json = json_decode($people_json, true);

$name = $decoded_json['name'];
$countries = $decoded_json['countries'];

foreach($countries as $country) {
    echo $name.' visited '.$country['name'].' in '.$country['year'].'.';
}
/*
Monty visited Spain in 1982.
Monty visited Australia in 1996.
Monty visited Germany in 1987.
*/

?>

让我们再来看看从JSON文件中提取信息的最后一个例子。这里是我们将从中提取数据的JSON文件。

{
    "customers": [
      {
        "name": "Andrew",
        "email": "andrew@something.com",
        "age": 62,
        "countries": [
          {
            "name": "Italy",
            "year": 1983
          },
          {
            "name": "Canada",
            "year": 1998
          },
          {
            "name": "Germany",
            "year": 2003
          }
        ]
      },
      {
        "name": "Sajal",
        "email": "sajal@something.com",
        "age": 65,
        "countries": [
          {
            "name": "Belgium",
            "year": 1994
          },
          {
            "name": "Hungary",
            "year": 2001
          },
          {
            "name": "Chile",
            "year": 2013
          }
        ]
      },
      {
        "name": "Adam",
        "email": "adam@something.com",
        "age": 72,
        "countries": [
          {
            "name": "France",
            "year": 1988
          },
          {
            "name": "Brazil",
            "year": 1998
          },
          {
            "name": "Poland",
            "year": 2002
          }
        ]
      },
      {
        "name": "Monty",
        "email": "monty@something.com",
        "age": 77,
        "countries": [
          {
            "name": "Spain",
            "year": 1982
          },
          {
            "name": "Australia",
            "year": 1996
          },
          {
            "name": "Germany",
            "year": 1987
          }
        ]
      }
    ]
}

这次我们在JSON数据中有两个嵌套数组。因此,我们将使用两个嵌套循环来获得不同客户访问的国家。

<?php

$people_json = file_get_contents('people.json');

$decoded_json = json_decode($people_json, true);

$customers = $decoded_json['customers'];

foreach($customers as $customer) {
    $name = $customer['name'];
    $countries = $customer['countries'];

    foreach($countries as $country) {
        echo $name.' visited '.$country['name'].' in '.$country['year'].'.';
    }
}

/*
Andrew visited Italy in 1983.
Andrew visited Canada in 1998.
Andrew visited Germany in 2003.

Sajal visited Belgium in 1994.
Sajal visited Hungary in 2001.
Sajal visited Chile in 2013.

Adam visited France in 1988.
Adam visited Brazil in 1998.
Adam visited Poland in 2002.

Monty visited Spain in 1982.
Monty visited Australia in 1996.
Monty visited Germany in 1987.
*/

?>

现在你应该对从文件中读取JSON数据的方法有一个大致的了解,这取决于文件的创建方式。

读取JSON数据而不事先知道密钥

到目前为止,我们在读取JSON数据时已经知道所有的键。这不一定是真的。幸运的是,一旦我们将文件存储为一个关联数组,我们仍然可以从文件中提取有用的信息。下面的例子应该可以说明问题。

{
    "kdsvhe": {
        "name": "Andrew",
        "age": 62
    },
    "lvnwfd": {
        "name": "Adam",
        "age": 65
    },
    "ewrhbw": {
        "name": "Sajal",
        "age": 72
    },
    "klkwcn": {
        "name": "Monty",
        "age": 77
    }
}

上述JSON中的键似乎是随机字符串,我们无法事先预测。然而,一旦我们把它转换成一个关联数组,我们就不再需要知道确切的键值来遍历数据。

<?php

$people_json = file_get_contents('people.json');

$decoded_json = json_decode($people_json, true);

foreach($decoded_json as $key => $value) {
    $name = $decoded_json[$key]["name"];
    $age = $decoded_json[$key]["age"];
    
    echo $name.' is '.$age.' years old.';
}

/*
Andrew is 62 years old.
Adam is 65 years old.
Sajal is 72 years old.
Monty is 77 years old.
*/

?>

在PHP中创建JSON数据

你也可以在PHP中借助于函数将你自己的数据变成一个格式良好的JSON字符串 [json_encode()](https://www.php.net/manual/en/function.json-encode.php).它基本上接受三个参数,但你通常只需要第一个参数,即在大多数情况下你要编码的值。

<?php

$people_info = [
    "customers" => [
        ["name" => "Andrew", "score" => 62.5],
        ["name" => "Adam", "score" => 65.0],
        ["name" => "Sajal", "score" => 72.2],
        ["name" => "Monty", "score" => 57.8]
    ]
];

echo json_encode($people_info);

/*
{"customers":[{"name":"Andrew","score":62.5},{"name":"Adam","score":65},{"name":"Sajal","score":72.2},{"name":"Monty","score":57.8}]}
*/

?>

你可能还需要使用一些标志,以获得所需格式的JSON字符串。例如,JSON_PRETTY_PRINT 标志可用于添加白色空间,以正确格式化JSON字符串。同样,你可以使用JSON_PRESERVE_ZERO_FRACTION 标志,以确保浮动值总是被存储为浮动值,即使它们在大小上等同于一些整数。你可以在官方文档中看到所有此类标志的列表

<?php

$people_info = [
    "customers" => [
        ["name" => "Andrew", "score" => 62.5],
        ["name" => "Adam", "score" => 65.0],
        ["name" => "Sajal", "score" => 72.2],
        ["name" => "Monty", "score" => 57.8]
    ]
];

echo json_encode($people_info, JSON_PRETTY_PRINT|JSON_PRESERVE_ZERO_FRACTION);

/*
{
    "customers": [
        {
            "name": "Andrew",
            "score": 62.5
        },
        {
            "name": "Adam",
            "score": 65.0
        },
        {
            "name": "Sajal",
            "score": 72.2
        },
        {
            "name": "Monty",
            "score": 57.8
        }
    ]
}
*/

?>

处理编码和解码过程中的错误

JSON格式要求我们遵循一套特定的规则来对字符串进行正确的编码和解码。例如,名字和值应该用双引号括起来,名字-值对后面不应该有尾部逗号。该 [json_last_error_msg()](https://www.php.net/manual/en/function.json-last-error-msg.php)函数可以帮助你找出你得到的是哪种错误,以便你可以采取适当的措施。下面是一个非常基本的例子。

<?php

$sample_json = '{"name": "value", }';

var_dump(json_decode($sample_json));
// NULL

echo json_last_error_msg();
// Syntax error

?>

最后的思考

在本教程中,你学会了如何用PHP从文件或字符串中读取JSON数据。我们还学习了如何将JSON转换为一个数组,并遍历它以提取我们想要的信息。现在你应该能够从一个不知道所有键值对的文件中的JSON中获取信息。在上两节中,我们介绍了如何在PHP中把数据串成JSON,以及在编码和解码过程中可能遇到的错误。

希望这能回答你关于在PHP中对JSON进行编码和解码的所有问题。