【问题标题】:Handling big user IDs returned by FQL in PHP在 PHP 中处理 FQL 返回的大用户 ID
【发布时间】:2011-02-23 20:50:18
【问题描述】:

我正在使用 FQL 从 Facebook 检索用户列表。为了保持一致性,我得到 JSON 格式的结果。这会导致一个问题 - 因为返回的 JSON 将用户 ID 编码为数字,所以 json_decode() 将这些数字转换为浮点值,因为有些太大而无法放入 int;当然,我需要这些 ID 作为字符串。

由于 json_decode() 在不接受任何行为标志的情况下做自己的事情,我很茫然。有关如何解决此问题的任何建议?

【问题讨论】:

    标签: php json facebook facebook-fql


    【解决方案1】:

    json_decode()可以将大整数转换为字符串,如果你在函数调用中指定一个标志:

    $array = json_decode($json, true, 512, JSON_BIGINT_AS_STRING)
    

    【讨论】:

    • 不知道我怎么会在文档中错过它。谢谢!
    • 这只是 PHP 的开发版本 - 至少根据 php.net 上的文档?
    • @Sebastian Hoitz ,页面很久没有更新了,根据它的参数应该可以从 PHP 5.3 开始(很久以前发布)。
    • 我刚在本地电脑上试了一下,报错json_decode只接受3个参数。
    • 实际上,根据文档,JSON_BIGINT_AS_STRING 是only available since 5.4。对于早期版本,preg_replace 解决方案可能效果最好,如下所述 - 我会做类似json_decode(preg_replace('/("\w+"):(\d+)/', '\\1:"\\2"', $jsonString), true)
    【解决方案2】:

    我已通过将 &format=json-strings 添加到我的 FQL api 调用中解决了该问题,如下所示:

    $myQuery = "SELECT uid2 FROM friend WHERE uid1=me()";
    $facebook->api("/fql?q=" . urlencode($myQuery) . "&format=json-strings")
    

    这告诉 facebook 将所有数字都用引号括起来,这导致 json_decode 两者都不使用 int-s 不浮动。

    因为我担心这个问题不仅限于 FQL,而是所有选择将某些 ID 表示为 BIG-INT 的图形 API 调用我已经尽可能修补 facebook 的 PHP SDK 以强制 Facebook 返回它的所有数字都是字符串。

    我已将这一行添加到_graph 函数中。 这将是 facebook_base.php 版本 3.1.1 中的第 738 行

    $params['format'] = 'json-strings';
    

    确定解决

    【讨论】:

    • 这适用于我们这些不使用最新 PHP 因而没有 JSON_BIGINT_AS_STRING 的人。
    • 这对我来说是最可靠的答案。以防你以后偶然发现: $myQuery = $facebook->api("/fql", array( "q" => "SELECT uid2 FROM friend WHERE uid1=me()", "format" => "json -strings"));
    【解决方案3】:

    我遇到了类似的问题,json_decode 将最近的 twitter/tweet ID 转换为指数数字。

    如果您希望您的 BIGINT 成为一个字符串并且拥有 PHP 5.3+,Björn 的回答非常棒。如果这些都不成立,另一种选择是提高 PHP 的浮点精度。 这可以通过几种不同的方式来完成...

    • 在您的 php.ini 中找到 precision 值并将其更改为 precision = 20
    • ini_set('precision', 20); 添加到您的 PHP 应用程序
    • php_value precision 20 添加到应用的 .htaccess 或虚拟主机文件中

    【讨论】:

    • 简单易行。顺便说一句,我们可以调整数字 '20' 以适应长值吗?
    • 我将此行添加到我的 .htaccess php_value 精度 20。在第一个站点上,这工作正常。但是当我在另一个站点上添加这个时,我得到了 500 内部服务器错误。我应该使用什么替代品?
    【解决方案4】:

    又快又脏,现在看来可以用了:

    $sJSON = preg_replace('/:(\d+)/', ':"${1}"', $sJSON);
    

    【讨论】:

      【解决方案5】:

      我用这个,效果几乎很好。

      json_decode(preg_replace('/("\w+"):(\d+)/', '\\1:"\\2"', $jsonString), true)
      

      当包含地理数据时,json 会中断,例如。 {"lat":54.2341} 导致"lat":"54".2341

      解决方案:

      $json = preg_replace('/("\w+"):(\d+)(.\d+)?/', '\\1:"\\2\\3"', $json);
      

      【讨论】:

      • 谢谢!那是给我剪的!不过,这个问题应该很快在 Facebook 方面得到解决:developers.facebook.com/bugs/254502934666393
      • 此模式也可以使用,因为它匹配一个捕获组中的数字和点:preg_replace('/("[\w.]+"):([\d.]+)/', '\\1:"\\2"', $json);
      【解决方案6】:

      这个(preg_replace('/("\w+"):(\d+)(.\d+)?/', '\\1:"\\2\\3"', $json);) 为我工作(用于解析来自 facebook api 的结果)

      【讨论】:

        【解决方案7】:

        PHP 的一个主要疏忽是浏览器不会阻塞以 BigInt(64 位)开头的整数,而是在那之前(53 位)。当 JSON 不支持 BigInt 时,将 BigInt 引入现代浏览器并没有多大帮助。所以我正在努力解决这个问题。

        我的方法是处理解码后的数组(在可能将其重新编码为字符串之前):

        function fix_large_int(&$value)
         {
          if (is_int($value) && $value > 9007199254740991)
            $value = strval($value);
         }
        $json_arr = json_decode($json_str, flags: JSON_BIGINT_AS_STRING | JSON_OBJECT_AS_ARRAY);
        echo('before: ' . json_encode($json_arr) . '<br />' . PHP_EOL);
        array_walk_recursive($json_arr, 'fix_large_int');
        echo('after:  ' . json_encode($json_arr) . '<br />' . PHP_EOL);
        

        数字 9007199254740991 是 JavaScript 的 Number.MAX_SAFE_INTEGER 值。在这里阅读:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER

        (顺便说一句,我到了这里,因为 Twitter API 的 stringify_ids 参数 blocks/idsfriends/ids 对我不起作用。不过,在我能找到的任何地方似乎都没有提到这一点。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-12-13
          相关资源
          最近更新 更多