为什么 PHP json_decode 无法解析这个 JSON

时间:2021-06-19 22:13:28

标签: php json parsing request

我有一个到服务器的 cURL 请求,它返回这种 jsonp 类型的数据,但我不知道为什么 PHP json_decode 在解析这个 JSON 文本时什么都不返回。 这是我从请求中得到的:

{
  "data": {
    "name": "Color Collections",
    "category": "collection",
    "palettes": [
      {
        "name": "America's Colors",
        "category": "collection",
        "colors": [
          {
            "number": "AC-1",
            "name": "Coastal Fog",
            "family": "Neutral",
            "url": "http://www.benjaminmoore.com/en-us/paint-color/ac-1?apiKey=9471009bd36bd062c688",
            "shortURL": "/ac-1",
            "hex": "CAC4B0",
            "r": 202,
            "g": 196,
            "b": 176,
            "exteriorAvailability": "available",
            "wetSampleSKU": null,
            "drySampleSKU": null,
            "eStoreAvailable": false,
            "productTypesAvailable": "paint",
            "stainOpacitiesAvailable": null
          },
          
        ],
        "colorList": [
          "AC-1",
          "AC-2",
          "AC-3",
          "AC-4",
          "AC-5",
          "AC-6",
          "AC-7",
          "AC-8",
          "AC-9",
          "AC-10",
          "AC-11",
          "AC-12",
          "AC-13",
          "AC-14",
          "AC-15",
          "AC-16",
          "AC-17",
          "AC-18",
          "AC-19",
          "AC-20",
          "AC-21",
          "AC-22",
          "AC-23",
          "AC-24",
          "AC-25",
          "AC-26",
          "AC-27",
          "AC-28",
          "AC-29",
          "AC-30",
          "AC-31",
          "AC-32",
          "AC-33",
          "AC-34",
          "AC-35",
          "AC-36",
          "AC-37",
          "AC-38",
          "AC-39",
          "AC-40",
          "AC-41",
          "AC-42"
        ],
        "code": "AC",
        "description": "42 soft hues inspired by the pale gray of our beautiful coastlines to the rich earth tones of our Southwestern deserts. ",
        "url": "http://www.benjaminmoore.com/en-us/for-your-home/color-gallery?apiKey=9471009bd36bd062c688#&ce_vm=2&ce_col=AC?apiKey=9471009bd36bd062c688",
        "rows": 7,
        "totalColors": 42,
        "eStoreProductCode": null
      },
    ]
  },
  "error": "",
  "countryCode": "en-us",
  "brand": "BenjaminMoore,Corotech,Coronado,Inslx,Lenmar,Maxum"
}

但即使我删除了一些部分,让它像这么短一样工作,但仍然没有从 PHP json_decode 返回任何内容。这是我的代码外观并告诉我这里发生了什么?为什么 PHP 不能解析这个?

 $jsonData = '{
    "data": {
      "name": "Color Collections",
      "category": "collection",
    },
    "error": "",
    "countryCode": "en-us",
    "brand": "BenjaminMoore,Corotech,Coronado,Inslx,Lenmar,Maxum"
  }';
  print_r( json_decode($jsonData, true));

2 个答案:

答案 0 :(得分:2)

这些都不是有效的 JSON。您始终可以通过 JSON Lint 之类的 lint 运行 JSON 以确保其有效。

你的小例子在第 4 行有一个额外的逗号:

  {
    "data": {
      "name": "Color Collections",
      "category": "collection", //<-------------here
    },
    "error": "",
    "countryCode": "en-us",
    "brand": "BenjaminMoore,Corotech,Coronado,Inslx,Lenmar,Maxum"
  }

你的大号在第 24 行多了一个逗号。

{
  "data": {
    "name": "Color Collections",
    "category": "collection",
    "palettes": [
      {
        "name": "America's Colors",
        "category": "collection",
        "colors": [
          {
            "number": "AC-1",
            "name": "Coastal Fog",
            "family": "Neutral",
            "url": "http://www.benjaminmoore.com/en-us/paint-color/ac-1?apiKey=9471009bd36bd062c688",
            "shortURL": "/ac-1",
            "hex": "CAC4B0",
            "r": 202,
            "g": 196,
            "b": 176,
            "exteriorAvailability": "available",
            "wetSampleSKU": null,
            "drySampleSKU": null,
            "eStoreAvailable": false,
            "productTypesAvailable": "paint",
            "stainOpacitiesAvailable": null
          }, //<------------------------------------- here
          
        ],
        "colorList": [
          "AC-1",
          "AC-2",
          "AC-3",
          "AC-4",
          "AC-5",
          "AC-6",
          "AC-7",
          "AC-8",
          "AC-9",
          "AC-10",
          "AC-11",
          "AC-12",
          "AC-13",
          "AC-14",
          "AC-15",
          "AC-16",
          "AC-17",
          "AC-18",
          "AC-19",
          "AC-20",
          "AC-21",
          "AC-22",
          "AC-23",
          "AC-24",
          "AC-25",
          "AC-26",
          "AC-27",
          "AC-28",
          "AC-29",
          "AC-30",
          "AC-31",
          "AC-32",
          "AC-33",
          "AC-34",
          "AC-35",
          "AC-36",
          "AC-37",
          "AC-38",
          "AC-39",
          "AC-40",
          "AC-41",
          "AC-42"
        ],
        "code": "AC",
        "description": "42 soft hues inspired by the pale gray of our beautiful coastlines to the rich earth tones of our Southwestern deserts. ",
        "url": "http://www.benjaminmoore.com/en-us/for-your-home/color-gallery?apiKey=9471009bd36bd062c688#&ce_vm=2&ce_col=AC?apiKey=9471009bd36bd062c688",
        "rows": 7,
        "totalColors": 42,
        "eStoreProductCode": null
      },
    ]
  },
  "error": "",
  "countryCode": "en-us",
  "brand": "BenjaminMoore,Corotech,Coronado,Inslx,Lenmar,Maxum"
}

答案 1 :(得分:1)

<块引用>

为什么 PHP json_decode 不能解析这个 JSON

 $jsonData = '{
    "data": {
      "name": "Color Collections",
      "category": "collection",
    },
    "error": "",
    "countryCode": "en-us",
    "brand": "BenjaminMoore,Corotech,Coronado,Inslx,Lenmar,Maxum"
  }';
  print_r( json_decode($jsonData, true));
<块引用>

这是我的代码,告诉我这里发生了什么?为什么 PHP 不能解析这个?

PHP 可以很好地解析这段 PHP 代码。而 json_decode 也执行标准操作,让我们看看这是什么。

首先是关于 json_decode 在您的示例中返回的内容的基础知识:NULL

有趣!

为什么这个 NULL 返回值很有趣?

首先,乍一看很明显,它不是解码字符串中的 JSON 文本,还是?

第二,来自 json_decode() is documentedNULL 返回值可以(但不能)表示解析 JSON 文本时出错。

这里是 PHP 手册的摘录:

<块引用>

返回值

以适当的 PHP 类型返回以 json [引用第一个参数] 编码的值。值 truefalsenull 分别作为 truefalsenull 返回。 null 如果 json [对第一个参数的引用] 无法解码或编码数据比嵌套限制更深,则返回。 [我强调]

由于 JSON 文本不是“null”,因此将 NULL 视为返回类型信号已经存在问题:

也许 json_decode 检测到无效输入并拒绝对其进行操作?或者它是否达到了嵌套限制(depth,第三个参数)?还是字符串不是 UTF-8 编码的?

问题上的问题,如何了解更多?

在您的情况下,您可以使用 json_last_error()json_last_error_msg() 函数找到它。因此,让我们看看这些函数返回的相关代码:int(4) 表示错误代码,string(12) "Syntax error" 表示错误消息。

哦,传递给 json_decode() 的 JSON 文本中存在语法错误。这意味着不是嵌套限制或字符编码问题!

让我们改写:

<块引用>

为什么 PHP json_decode 不能解析这个 JSON

因为 JSON 有语法错误。


好吧,这现在看起来很简单,对吧?但是等等,PHP 的 json_decode() 有什么资格作为 JSON?好吧,再次查看手册是必须的:

<块引用>

PHP 实现了原始 » RFC 7159 中指定的 JSON 超集。

所以(更)正确的答案是:


因为 JSON 文本不在 RFC 7159 JavaScript 对象表示法 (JSON) 数据交换格式中。


现在这是给老板留下深刻印象的声明!

既然这个答案已经不通了,接下来就是:如何处理?好吧,检查返回类型和错误函数 - 现在推荐 - 使用适当的标志调用 json_decode() 以抛出错误:

$result = json_decode($jsonData, true, 512, JSON_THROW_ON_ERROR);

这突出了解码、字符编码和限制命中等直接可见并委托给标准错误处理程序,以便您可以自上而下地编写代码。


很好,感谢所有的鱼,一切都很好,花花公子,但是,现在我知道有一个错误,但不工作的情况还是和之前一样,那为什么snap 是无效的 JSON?

如果这仍然让您感到困惑,或者这可能是前面的第一个问题(而不是问题中所写的 PHP 或 json_decode),那么答案就更简单了:您需要使用一种工具来告诉您为什么 JSON 已损坏。

这可以是语法高亮,但更有可能是您希望验证器显示实际错误。

例如在 IDE 中(此处为 PhpStorm):

  1. 将字符串的内容标记为 JSON,例如使用 PHPDoc:
    $jsonData = /** @lang JSON */ '{
        "data": {
        ...
    
  2. 在 IDE 突出显示的 JSON 文本字符串中找到任何错误(取决于您使用的产品,这可能会有所不同): enter image description here 这里是红色波浪下划线
  3. 激活它的错误信息以获取更多信息(例如用鼠标悬停并等待工具提示出现): enter image description here

答案再次是语法错误,这里提示

<块引用>

JSON 标准不允许尾随逗号

现在还有什么好说的?如果您看到 json_decode 错误并且您看不到 JSON 已损坏,请先验证它。仅通过查看 JSON 文本就很容易错过 JSON 编码错误。而且往往不值得。无效的 JSON?算了吧。大功告成。

激活 JSON_THROW_ON_ERROR,您的代码就可以保持不变,现在包含电池。