在 PHP 中处理 JSON 数组和对象

编辑

在 PHP 中处理 JSON 数组和对象

编辑

客户端的一个常见混淆点在于 JSON 数组和对象,以及如何在 PHP 中指定它们。特别是,空对象和对象数组会导致问题。此页面向您展示了 Elasticsearch JSON API 中使用的常见模式以及如何将其转换为 PHP 表示。

空对象

编辑

Elasticsearch API 在多个位置使用空 JSON 对象,这可能会导致 PHP 出现问题。与其他语言不同,PHP 没有空对象的“简写”表示法,许多开发人员不知道如何指定空对象。

考虑为查询添加高亮显示

{
    "query" : {
        "match" : {
            "content" : "quick brown fox"
        }
    },
    "highlight" : {
        "fields" : {
            "content" : {} 
        }
    }
}

这个空 JSON 对象会导致问题。

问题在于 PHP 会自动将 "content" : {} 转换为 "content" : [],这不再是有效的 Elasticsearch DSL。我们需要告诉 PHP 空对象明确是一个对象,而不是一个数组。要在 PHP 中定义此查询,您可以执行以下操作

$params['body'] = array(
    'query' => array(
        'match' => array(
            'content' => 'quick brown fox'
        )
    ),
    'highlight' => array(
        'fields' => array(
            'content' => new \stdClass() 
        )
    )
);
$results = $client->search($params);

我们使用通用的 PHP stdClass 对象来表示空对象。JSON 现在可以正确编码。

通过使用显式的 stdClass 对象,我们可以强制 json_encode 解析器正确输出空对象,而不是空数组。这个冗长的解决方案是唯一可以在 PHP 中实现目标的方法……没有空对象的“简写”版本。

对象数组

编辑

Elasticsearch DSL 中的另一种常见模式是对象数组。例如,考虑为您的查询添加排序

{
    "query" : {
        "match" : { "content" : "quick brown fox" }
    },
    "sort" : [  
        {"time" : {"order" : "desc"}},
        {"popularity" : {"order" : "desc"}}
    ]
}

"sort" 包含一个 JSON 对象数组。

这种安排非常常见,但 PHP 中的构造可能很棘手,因为它需要嵌套数组。PHP 的冗长性往往会掩盖实际发生的情况。要构造一个对象数组,您实际上需要一个数组的数组

$params['body'] = array(
    'query' => array(
        'match' => array(
            'content' => 'quick brown fox'
        )
    ),
    'sort' => array(    
        array('time' => array('order' => 'desc')),  
        array('popularity' => array('order' => 'desc')) 
    )
);
$results = $client->search($params);

此数组编码 "sort" : [] 数组

此数组编码 {"time" : {"order" : "desc"}} 对象

此数组编码 {"popularity" : {"order" : "desc"}} 对象

如果您使用的是 PHP 5.4 或更高版本,我们强烈建议您使用简短的数组语法。它使这些嵌套数组更容易阅读

$params['body'] = [
    'query' => [
        'match' => [
            'content' => 'quick brown fox'
        ]
    ],
    'sort' => [
        ['time' => ['order' => 'desc']],
        ['popularity' => ['order' => 'desc']]
    ]
];
$results = $client->search($params);

空对象数组

编辑

有时,您会遇到需要前面两种模式的 DSL。函数评分查询就是一个很好的例子,它有时需要一个对象数组,而其中一些对象可能是空 JSON 对象。

给定此查询

{
   "query":{
      "function_score":{
         "functions":[
            {
               "random_score":{}
            }
         ],
         "boost_mode":"replace"
      }
   }
}

我们可以使用以下 PHP 代码构建它

$params['body'] = array(
    'query' => array(
        'function_score' => array(
            'functions' => array(  
                array(  
                    'random_score' => new \stdClass() 
                )
            )
        )
    )
);
$results = $client->search($params);

这将编码对象数组:"functions" : []

这将编码数组内的对象:{ "random_score": {} }

这将编码空 JSON 对象:"random_score": {}