在 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": {}