8

因此,我正在创建一个 vim 脚本,该脚本需要将 JSON 文件加载并解析到本地对象图中。我进行了搜索,但找不到任何处理 JSON 文件的本机方式,并且我不想向脚本添加任何依赖项。所以我编写了自己的函数来解析 JSON 字符串(从文件中获取),但它真的很慢。目前,我像这样遍历文件中的每个字符:

let len = strlen(jsonString) - 1
let i = 0
while i < len
    let c = strpart(jsonString, i, 1)
    let i += 1
    " A lot of code to process file....
    " Note: I've tried short cutting the process by searching for enclosing double-quotes when I come across the initial double quotes (also taking into account escaping '\' character.  It doesn't help
endwhile

我也试过这个方法:

for c in split(jsonString, '\zs')
    " Do a lot of parsing ....
endfor

作为参考,大约 29,000 个字符的文件需要大约 4 秒的时间来处理,这是不可接受的。

有没有更好的方法来遍历 vim 脚本中的字符串?

或者更好的是,我是否错过了解析 JSON 的本机函数?

更新:

我要求不依赖,因为我:

  1. 不想和他们打交道
  2. 真正想要一些想法,以便在没有其他人的工作的情况下做到这一点。
  3. 有时我只是喜欢手动做事,即使问题已经解决了。

我根本不反对插件或依赖项,只是我很好奇。因此问题。

我最终创建了自己的函数来解析 JSON 文件。我正在创建一个可以解析package.json与 node.js 模块关联的文件的脚本。因此,只要我检索到所需的信息,我就可以依靠相当一致的格式并退出处理。这通常会删除文件的大块,因为大多数开发人员将文件的最大块,即他们的“自述文件”部分放在最后。因为package.json文件是严格定义的,所以我让这个过程有些脆弱。它假定一个根字典{ }并积极寻找某些条目。你可以在这里找到脚本:https ://github.com/ahayman/vim-nodejs-complete/blob/master/after/ftplugin/javascript.vim#L33 。

当然,这并不能回答我自己的问题。这只是我独特问题的解决方案。我会等几天等待新的答案,然后在赏金结束前挑选出最好的答案(我已经在手机上设置了闹钟)。

4

3 回答 3

6

依赖最少的最简单的解决方案就是使用json_decodevim 函数。

let dict = json_decode(jsonString)
于 2017-01-18T07:49:25.627 回答
4

尽管 Vim 的起源可以追溯到很久以前,但它的内部 string() eval() 表示非常接近 JSON,除非您需要特殊字符,否则它可能会起作用。

如果需要,您可以在此处查找甚至支持 true/false/null 的实现: https ://github.com/MarcWeber/vim-addon-json-encoding

更好地使用该库(vim-addon-manager 允许轻松安装依赖项)。现在这是否足够好取决于您的数据。

现在 Benjamin Klein 将您的问题发布到 vim_use 这就是我回复的原因。如果你订阅了 Vim 邮件列表,就会得到最好和最快速的回复。转到 vim.sf.net 并点击社区链接。你不能指望 Vim 社区刮掉 stackoverflow。

我已经将关键字“json”和“parsing”添加到那个更容易找到的小代码中。

如果此解决方案对您不起作用,您可以尝试许多 :h if_* 绑定或编写一个外部脚本来提取您要查找的信息,或者将 JSON 转换为 Vim 的字典表示,可以通过 eval() 转义特殊字符读取您正确关心的字符。

于 2013-09-30T23:54:39.297 回答
2

如果您寻求完全正确的解决方案,忽略依赖项是您能做的最糟糕的事情之一。eval()@MarcWeber 提到的变体是最快的变体之一,但它有其缺点:

  1. 使用我在评论中提到的安全评估解决方案使其不再是最快的。事实上,在你使用它之后,它会eval()变慢一个数量级以上(在我的测试中为 0.02 秒对 0.53 秒)。
  2. 它不尊重代理对。
  3. 它不能用于验证您是否拥有正确的 JSON:它接受一些"\<C-o>"不是 JSON 字符串的字符串(例如 ),并且它允许尾随逗号。
  4. 它无法给出正常的错误消息。如果您使用vam#VerifyIsJSON我在第 1 页中提到的,它会严重失败。
  5. 它无法加载浮点值,例如1e10(vim 要求数字看起来像,但允许1.0e10像 1e10这样的数字:请注意第一段中的“和/或”)。

. 以上所有(除了第一个)语句也适用于vim-addon-json-encoding@MarcWeber 提到的,因为它使用 eval。还有一些其他的可能性:

  1. 最快和最正确的是使用 python: pyeval('json.loads(vim.eval("varname"))')。不比 eval 快,但在其他可能性中最快。(在我的测试中为 0.04:大约慢两倍eval()

    请注意,我pyeval()在这里使用。如果您想要缺少此功能的 vim 版本的解决方案,它将不再是最快的版本之一。

  2. 使用我的json.vim插件。与 failed 相比,它的错误报告略好,与 failed 相比vam#VerifyIsJSON略差,eval()并且可以正确加载浮点数。它可用于验证字符串(它不接受"\<C-a>"),但它加载带有尾随逗号的列表就好了。它不支持代理对。它也很慢:在我使用的测试中(它使用 279702 个字符的长字符串)加载需要 11.59 秒。如果可能的话,Json.vim 会尝试使用 python。

  3. 为了获得最佳的错误报告,您可以使用yaml.vim并从中清除 YAML 支持,只留下 JSON(我曾经为 pyyaml 做过同样的事情,尽管在 python 中:请参阅在 powerline 中使用的标记json库:它是 pyyaml 减去 YAML 的东西加上带分数的班级)。但是这个变体甚至比 json.vim 还要慢,并且只应该在您需要的主要内容是错误报告时使用:加载相同的 279702 字符长字符串需要 207 秒。

请注意,唯一提到的同时满足“无依赖关系”和“无 python”要求的变体是eval(). 如果您对它的缺点不满意,则必须放弃其中一项或两项要求。或者复制粘贴代码。虽然如果你考虑到速度,只剩下两个候选者:eval()和 python:如果你想快速解析 json,你真的必须使用 C,只有这些解决方案将大部分时间花在用 C 编写的函数上。

大多数其他解释器(ruby/perl/TCL)没有pyeval()等价物,所以即使他们的 JSON 实现是用 C 编写的,它们也会变慢。其他一些(lua/racket (mzscheme))有pyeval()等价物,但例如luaeval('{}')为零意味着你会必须显式添加额外的步骤并递归地将对象转换为 vim 字典和列表(例如luaeval('vim.dict({})')),这将影响性能。不能说什么mzeval(),但我从来没有听说过有人实际使用带有 vim 的球拍(mzscheme)。

于 2013-10-01T04:51:48.143 回答