如何防止 json_encode() 删除含有无效字符的字符串

2024-01-10

有没有办法保留json_encode()从返回null对于包含无效(非 UTF-8)字符的字符串?

在复杂的系统中进行调试可能会很痛苦。实际看到无效字符或者至少将其省略会更合适。就目前情况而言,json_encode()会默默地丢弃整个字符串。

示例(UTF-8 格式):

$string = 
  array(utf8_decode("Düsseldorf"), // Deliberately produce broken string
        "Washington",
        "Nairobi"); 

print_r(json_encode($string));

结果是

[null,"Washington","Nairobi"]

期望的结果:

["D�sseldorf","Washington","Nairobi"]

Note: I am not希望使损坏的字符串在 json_encode() 中工作。我正在寻找更容易诊断编码错误的方法。 Anull字符串对此没有帮助。


php 确实尝试抛出错误,但是仅当您关闭 display_errors 时。这很奇怪,因为display_errors设置仅用于控制是否将错误打印到标准输出,而不是控制是否触发错误。我想强调的是,当你有display_errors即使您可能会看到各种其他 php 错误,php 也不只是隐藏此错误,它甚至不会触发它。这意味着它不会显示在任何错误日志中,也不会调用任何自定义 error_handlers。错误永远不会发生。

下面是一些代码来演示这一点:

error_reporting(-1);//report all errors
$invalid_utf8_char = chr(193);

ini_set('display_errors', 1);//display errors to standard output
var_dump(json_encode($invalid_utf8_char));
var_dump(error_get_last());//nothing

ini_set('display_errors', 0);//do not display errors to standard output
var_dump(json_encode($invalid_utf8_char));
var_dump(error_get_last());// json_encode(): Invalid UTF-8 sequence in argument

这种奇怪而不幸的行为与这个错误有关https://bugs.php.net/bug.php?id=47494 https://bugs.php.net/bug.php?id=47494以及其他一些问题,而且看起来它永远不会被修复。

解决方法:

在将字符串传递给 json_encode 之前清理字符串可能是一个可行的解决方案。

$stripped_of_invalid_utf8_chars_string = iconv('UTF-8', 'UTF-8//IGNORE', $orig_string);
if ($stripped_of_invalid_utf8_chars_string !== $orig_string) {
    // one or more chars were invalid, and so they were stripped out.
    // if you need to know where in the string the first stripped character was, 
    // then see http://stackoverflow.com/questions/7475437/find-first-character-that-is-different-between-two-strings
}
$json = json_encode($stripped_of_invalid_utf8_chars_string);

http://php.net/manual/en/function.iconv.php http://php.net/manual/en/function.iconv.php

手册说

//IGNORE默默地丢弃目标中非法的字符 字符集。

因此,通过首先删除有问题的字符,理论上 json_encode() 不应该得到任何会阻塞并失败的内容。我还没有验证 iconv 的输出//IGNOREflag 与有效 utf8 字符是什么的 json_encodes 概念完全兼容,因此买家要小心......因为可能存在仍然失败的边缘情况。呃,我讨厌字符集问题。

Edit
在 php 7.2+ 中,似乎有一些新标志json_encode: JSON_INVALID_UTF8_IGNORE and JSON_INVALID_UTF8_SUBSTITUTE
目前还没有太多文档,但就目前而言,此测试应该可以帮助您了解预期的行为:https://github.com/php/php-src/blob/master/ext/json/tests/json_encode_invalid_utf8.phpt https://github.com/php/php-src/blob/master/ext/json/tests/json_encode_invalid_utf8.phpt

而且,在 php 7.3+ 中,有一个新标志JSON_THROW_ON_ERROR. See http://php.net/manual/en/class.jsonexception.php http://php.net/manual/en/class.jsonexception.php

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何防止 json_encode() 删除含有无效字符的字符串 的相关文章

随机推荐

  • 双递归定义列表的双无限列表

    Context 我问的是修补递归定义的列表 https stackoverflow com q 53988970 12274另一天 我现在尝试通过在 2D 列表 列表的列表 上操作来将其提升一个级别 我将使用帕斯卡三角形作为示例 例如这个美
  • 如何在字符串中找到匹配的大括号对?

    假设我有一个字符串 付费 8个工作时间 公司规则 现在我想检查这个完整的字符串是否用括号括起来 基本上我想检查字符串是否是这样的 付费 8个工作时间 公司规则 如果它已经用括号括起来 那么我将保留它原样 否则我会将括号应用于完整的字符串 以
  • 如何从多行文本框中获取换行?

    在我的 windows forms C 应用程序中 我有一个 WordWrap true 的多行文本框 将 Text 属性设置为长字符串后 我需要获取通过换行生成的所有行 它与 Lines 属性不同 因为我的文本不包含换行符 我已经找到了使
  • 在启用自动筛选器且数据位于“要复制的行”的情况下,将一行复制并添加到工作表的末尾

    更新 替代解决方案不幸的是 我的问题没有答案 我需要继续该项目 我查看了之前编写的一些代码并决定使用它 我发现的解决方案不如用户 djbrett 建议的解决方案优雅 但它有效 我添加了一行额外的行 宏可以从中继续计数 有兴趣的可以看下面的代
  • 如何记录基于函数的视图参数?

    我正在使用 Django 1 11 和 Django REST Framework 3 7 开发 REST API 我安装了Django REST 招摇 https github com marcgibbons django rest sw
  • Clojure 实现可以快速启动吗?

    time java jar clojure 1 4 0 jar e println Hello world Hello world real 0m4 586s time python clojure py c py print Hello
  • 错误:tensorboard 2.0.2 要求 setuptools>=41.0.0,但您将拥有不兼容的 setuptools 40.6.2

    安装的时候出现这个错误 这会引起问题吗 错误 tensorboard 2 0 2 要求 setuptools gt 41 0 0 但您将拥有不兼容的 setuptools 40 6 2 我刚刚做了一个pip install setuptoo
  • 持久图形 WinForms

    我有一个 WinForms 应用程序 我必须在控件之间画一些线 这些行需要持久存在 所以我覆盖了表单OnPaint event 问题是 重新绘制的线条不是很平滑 我正在创建图形如下 Graphics g g this CreateGraph
  • 警告来源未知:“找不到虚拟表的链接器符号...”

    几天以来 我在调试时收到一条警告消息 我找不到它来自哪里 我已经在谷歌搜索并发现类似的东西 因为我有一个静态变量 但取出来并不能改变什么 这是main method int main int argc char argv if argc 2
  • 如何列出连接字符串列表的所有可能方法

    我想列出连接字符串列表的所有可能方法 例如 Input strings hat bag cab Output concatenated hatbag hatcab hatbagcab hatcabbag baghat bagcab bagh
  • 使用 JS 切换/显示一个定义的 DIV

    我有一把小提琴给你 http jsfiddle net vSs4f http jsfiddle net vSs4f 我想展示div sub menu只需点击一下a haschildren 如果身体加载div sub menu应该关闭 如果我
  • 将 VS2010 类图导出到 Visio

    我正在使用 VS2010 创建类图 有什么方法可以导入 VS2010 生成的类图以导入到 MS Visio 中吗 右键单击 Visual Studio 中的类图 然后选择 将图导出为图像 Choose 增强型图元文件格式 emf Visio
  • Spring Integration 中的 REST 端点使消息通道成为多线程

    我有一个非常简单的 Spring Boot 应用程序 它提供了几个静态端点 这应该驱动将 sftp 文件上传到 sftp 服务器 我的要求是 如果有多个文件 则文件应该排队 我希望通过 sftp spring 集成工作流程的默认行为来实现这
  • 使用 DOMXPath 保留

    标签内的换行符?

    我目前正在使用 PHP 和DOMXPath获取所有的内容 p 网页的元素 p
  • 如何过滤 SCons Glob 结果?

    我有时想从 SCons 的 Glob 结果中排除某些源文件 通常是因为我想用不同的选项编译该源文件 像这样的事情 objs env Object Glob cc objs env Object SpeciallyTreatedFile cc
  • 如何在不更改图像的情况下更新ALAsset的exif?

    I use setImageData metadata completionBlock of ALAsset更新资产的 exif 元数据 我只想更新元数据 但此方法需要imageData作为第一个参数 我使用下面的代码来生成imageDat
  • jQuery.event.props 未定义

    我在用着jquery event move https github com stephband jquery event move在触摸设备上创建移动事件 该脚本在第 580 行抛出错误 570 Make jQuery copy touc
  • 地理定位在设备 ionic3 中不起作用

    我正在从事 ionic 3 基于位置的工作 我无法在这里获取当前位置的纬度和经度 我提到了我的可用代码 它在浏览器级别工作正常 但在移动设备中无法工作 code ionic cordova plugin add cordova plugin
  • PIMPL 习惯用法真的在实践中使用吗?

    我正在看书 卓越的 C Herb Sutter 所著 在那本书中我了解了 PIMPL 习惯用法 基本上 这个想法是创建一个结构private的对象class并将它们动态分配给减少编译时间 并且还以更好的方式隐藏私有实现 例如 class X
  • 如何防止 json_encode() 删除含有无效字符的字符串

    有没有办法保留json encode 从返回null对于包含无效 非 UTF 8 字符的字符串 在复杂的系统中进行调试可能会很痛苦 实际看到无效字符或者至少将其省略会更合适 就目前情况而言 json encode 会默默地丢弃整个字符串 示