【发布时间】:2021-08-11 22:45:50
【问题描述】:
我的特殊用例是记录 HTTP 请求参数、响应和标头。我希望能够只存储一部分数据,而不会丢失已存储的数据结构。
让我们举个简单的例子,HTTP 标头:
const JSON_OPTIONS = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
function limitSizeOfHeaders(array $headers, int $maxSize) {
$currentSize = 0;
$limited = [];
foreach($headers as $name => $values) {
$headerSize = strlen(json_encode([$name => $values], JSON_OPTIONS)) - 1;
if(($currentSize + $headerSize) > $maxSize) {
break;
}
$limited[$name] = $values;
$currentSize += $headerSize;
}
return $limited;
}
echo "\n".json_encode(limitSizeOfHeaders([
'Authorization' => 'Bearer aX93nd11a9a0asaZzt432rSAu',
'Content-Type' => 'form/urlencoded',
'Accept' => 'application/json',
'Cookie' => 'PHPSESSID=a9d78e29a2c150dee3'
], 120), JSON_OPTIONS|JSON_PRETTY_PRINT)."\n\n";
产生输出:
{
"Authorization": "Bearer aX93nd11a9a0asaZzt432rSAu",
"Content-Type": "form/urlencoded",
"Accept": "application/json"
}
但标题具有非常可预测的结构。每个标头都是包含一个或多个字符串数组的对象的属性。一个 Json 响应体,可能没有那么简单。甚至表单数据也可以被解析为具有不同深度的多维数组。
所以我真正想要的是:
function limitArraySize(array $anything): array
我认为这是一个有趣的问题,其他人可能已经解决了。
【问题讨论】:
-
我认为您必须自己跟踪解析堆栈,然后当您达到最终长度时,您就会知道有多少未终止的层。可能大多数时候,在达到 maxSize 之前,您还有一些回旋余地来添加终止符,或者如果没有,您可以删除一个元素。但是没有办法避免在您自己的逻辑中考虑输出语法。
-
我不是在评判你,但我想不出我想记录标题的特定用例,我要么不感兴趣在所有这些中,或者我仅对其中一些感兴趣,但会发现在不知道发生截断的情况下列出可能被截断的列表是可以接受的。
-
@ChrisHaas headers 只是一个例子。但我绝对想记录我发出的任何 API 请求的响应标头,最多几千字节,但我不希望它占用我所有的内存/硬盘空间,对于任何 json 响应都一样
-
如果长度是一个问题,那么为什么要使用 PRETTY_PRINT?