只解析json的第一级

时间:2016-09-29 09:14:44

标签: php arrays json string

我有这种json文件:

{
"params": {
    "apiKey": "key",
    "sessionId": "123433890",
    "lang": "en",
    "timezone": "America/New_York",
    "query": "hi all",
    "latitude": "37.459157",
    "longitude": "-122.17926",
    "context": "[{"
     name ": "
     weather ","
     lifespan ": 4}]"
}

}

由于

,它无效json
"context": "[{"
     name ": "
     weather ","
     lifespan ": 4}]"

我无法用json_decode解码它。

所以我想知道是否可以只解码第一个键。所以结果可能看起来像

    array(1) {
  'parameters' =>
  array(8) {
    'apiKey' =>
    string(32) "key"
    'sessionId' =>
    string(10) "123433890"
    'lang' =>
    string(2) "en"
    'timezone' =>
    string(16) "America/New_York"
    'query' =>
    string(16) "hi all"
    'latitude' =>
    string(9) "37.459157"
    'longitude' =>
    string(10) "-122.17926"
    'context' =>
    string(16) "[{"name ": "weather ","lifespan ": 4}]"
  }
}

谢谢!

这也是有效的json,但不能用json_decode解码。

    {
    "query": [
        "and for tomorrow"
    ],
    "contexts": "[{'name':'weather', 'lifespan' : 4}]",
    "location": {
        "latitude": 37.459157,
        "longitude": -122.17926
    },
    "timezone": "America/New_York",
    "lang": "en",
    "sessionId": "1234567890"
}

3 个答案:

答案 0 :(得分:1)

您的JSON确实无效。它应该是这样的:

{
  "params": {
    "apiKey": "key",
    "sessionId": "123433890",
    "lang": "en",
    "timezone": "America/New_York",
    "query": "hi all",
    "latitude": "37.459157",
    "longitude": "-122.17926",
    "context": [{"name":"weather","lifespan": 4}]
  }
}

错误是context键值被放在引号中,虽然它不应该是,因为它不是字符串,而是嵌套对象。

如果您无法控制该文件,并且无法修复该文件,那么您可以使用此代码,该代码将在您阅读后尝试为您修复:

// Invalid JSON as read from your file:
$json = '{
  "params": {
    "apiKey": "key",
    "sessionId": "123433890",
    "lang": "en",
    "timezone": "America/New_York",
    "query": "hi all",
    "latitude": "37.459157",
    "longitude": "-122.17926",
    "context": "[{"
     name ": "
     weather ","
     lifespan ": 4}]"
  }
}';
// Fix malformed JSON
$json = preg_replace_callback('~"([\[{].*?[}\]])"~s', function ($match) {
    return preg_replace('~\s*"\s*~', "\"", $match[1]);
}, $json);
// Now you can do:
$arr = json_decode($json, true);

上述代码的结果是$arr将包含此内容:

array (
  'params' => array (
    'apiKey' => 'key',
    'sessionId' => '123433890',
    'lang' => 'en',
    'timezone' => 'America/New_York',
    'query' => 'hi all',
    'latitude' => '37.459157',
    'longitude' => '-122.17926',
    'context' => array (
      array (
        'name' => 'weather',
        'lifespan' => 4,
      ),
    ),
  ),
)

eval.in上看到它。

请注意context属性如何具有结构化信息(数组)。

代码说明

首先搜索以下模式:

~"([\[{].*?[}\]])"~s

~只是正则表达式的分隔符。然后:

  • ":匹配双引号
  • ( ... ):定义我们想要实际获取的部分:我们要删除最外面的双引号,因此它们不在这些括号中。
  • [\[{]:匹配其中一个文字字符:[{
  • .*?:匹配任何字符,但不能超过继续(?使其非贪婪,即懒惰)。
  • [}\]]:匹配其中一个文字字符:}]
  • s:这是一个修饰符,可使.也与换行符匹配

对于每个匹配,preg_replace_callback将调用我们作为第二个参数传递的函数,并将其传递给数组。数组的第一个元素将是完全匹配,而第二个元素将代表捕获的部分,即括号之间的部分(一个有我们感兴趣的部分):

$match[1]

我们在其上应用一个新的正则表达式,它会删除双引号周围的所有空格,包括换行符。这样,像name这样的密钥名称将用双引号紧密包装,因为它应该是:

~\s*"\s*~s

同样,~只是正则表达式的分隔符。

  • \s*:匹配任意数量的空白区域,包括换行符

必须将修改后的字符串返回到外部preg_replace_callback函数,该函数将使用它将其插入到最终结果字符串中。

修复真实原因

当然,如果你可以控制文件或如何生成文件,那么请解决此问题的原因。

请注意,有效的JSON 使用单引号来分隔字符串。它们必须是双引号。

答案 1 :(得分:0)

你提到的第二个json无法解码。

以下是解决方案:

$test = '{
"query": [
    "and for tomorrow"
],
"contexts": "[{\'name\':\'weather\', \'lifespan\' : 4}]",
"location": {
    "latitude": 37.459157,
    "longitude": -122.17926
},
"timezone": "America/New_York",
"lang": "en",
"sessionId": "1234567890"
}';

$j = json_decode($test);

print_r($j);

答案 2 :(得分:-1)

如何生成此json

你的json生成可能有一些错误

应生成正确的json,如下所示

{
    "params": {
        "apiKey": "key",
        "sessionId": "123433890",
        "lang": "en",
        "timezone": "America/New_York",
        "query": "hi all",
        "latitude": "37.459157",
        "longitude": "-122.17926",
        "context": [{
         "name ":" ",
         "weather" :"a",
         "lifespan ": 4}]
    }

}

您可以查看相同的Here

我认为您传递给上下文的值应该是您缺少的数组。