使用 Oj.dump 序列化时将符号转换为字符串

Posted

技术标签:

【中文标题】使用 Oj.dump 序列化时将符号转换为字符串【英文标题】:Convert symbols to string when serializing with Oj.dump 【发布时间】:2014-01-28 12:45:09 【问题描述】:

问题摘要:我正在尝试使用 Oj gem 将哈希序列化为 JSON。似乎 Oj 不会自动将哈希的符号键转换为字符串。我想知道 Oj 在序列化期间是否可以选择“字符串化”?

这是我的哈希示例:

example_hash = 
 :id=>1234,
  :asset_number=>"1234-5678",
  :latitude=>34.78495,
  :longitude=>-92.12899,
  :last_tracking_record_id=>123456789,
  :bearing=>42,
  :threat_level=>:severe

上面是这样渲染的:

render json: Oj.dump(example_hash)

不幸的是,生成的 JSON 具有与上面完全相同的键,这意味着我需要像这样访问 javascript 中的元素:response[:asset_number]。由于客户端代码是几个月前实现的,现在才添加 Oj,我希望找到一种在序列化服务器端期间对键进行字符串化的方法。

Oj 有一个名为 symbol_keys 的选项,它是一个布尔值,但将其设置为 truefalse 似乎在这方面没有任何效果。

到目前为止,我发现的唯一解决方案是按照this answer 中的建议使用with_indifferent_access,但是在某些情况下,我有哈希数组;虽然我可以在技术上为该数组中的每个哈希调用该方法,但鉴于 Oj 旨在加速 Json 序列化,我更愿意找到一种方法来使用 Oj 本身执行此操作。最后,我想知道 Oj 中是否有一个选项或设置可以在 序列化期间执行此操作。

【问题讨论】:

【参考方案1】:

在我写这个问题的时候,我找到了答案。由于我在 *** 上找不到与此问题相关的任何其他答案(特别是关于 Oj gem),我将保留这篇文章,希望它能帮助其他人。

根据this previously discussed issue on GitHub,将选项mode 设置为:compat 确实会将符号转换为字符串。所以我的渲染线现在看起来像这样:

render json: Oj.dump(example_hash, mode: :compat)

根据Oj documentation for default_options:compat模式定义如下:

...与其他系统兼容。它会序列化任何对象,但会 检查对象是否实现了 to_hash() 或 to_json() 方法。 如果其中任何一个存在,则该方法用于序列化对象。这 to_hash() 更灵活并产生更一致的输出,因此它 优先于 to_json() 方法。如果既不是 to_json() 或 to_hash() 方法存在然后 Oj 内部对象变量 使用编码。

因此,如果我的解释正确,那么这个解决方案似乎有效,因为它最终使用了 Hash 类的 to_json 方法。

我不确定我是否影响了性能(正面或负面),但至少它使我不必在数组的情况下手动调用with_indifferent_accessto_json

更新

在性能方面,cmwright 做了一些基准测试,得出了以下结果:

Rehearsal ----------------------------------------------
json        13.990000   0.250000  14.240000 ( 14.257051)
oj default   3.260000   0.230000   3.490000 (  3.491028)
oj compat    3.360000   0.240000   3.600000 (  3.593109)
------------------------------------ total: 21.330000sec

                 user     system      total        real
json        13.740000   0.240000  13.980000 ( 13.992641)
oj default   3.020000   0.230000   3.250000 (  3.248077)
oj compat    3.060000   0.230000   3.290000 (  3.286443)

似乎compat 选项至少与默认的Oj 选项相当,并且比普通的'ol to_json 更有效。

这是包含基准代码的gist。

【讨论】:

我刚刚做了一些基准测试,以确保兼容模式不会影响性能,并对我的用例感到惊喜。我使用带有 10,000 个键的哈希 (string => int) 并通过 Benchmark.bmbm 得到以下结果(在这些 cmets 中似乎无法格式化): json 14.550000 0.270000 14.820000 ( 14.855023) oj default 3.420000 0.250000 3.670000 ( 3.684兼容 3.500000 0.260000 3.760000 (3.758900) @cmwright 啊,非常好。过了一段时间我很确定没有性能问题,但我从来没有做任何实际的基准测试。很高兴知道。这个问题的浏览量似乎比我预期的要多,所以您介意我将您的数据添加到答案中吗(当然有适当的信用)? 是的,绝对可以。我可以发布我下次在计算机上使用的代码的要点 @cmwright 太好了,谢谢!答案已更新。我猜compat 似乎对性能的影响很小,但差异似乎几乎可以忽略不计(假设它不是侥幸)。【参考方案2】:

使用 generate 方法可以得到相同的输出。

Oj.generate(a: `test`) 

【讨论】:

以上是关于使用 Oj.dump 序列化时将符号转换为字符串的主要内容,如果未能解决你的问题,请参考以下文章

字符串编码ord,chr,字面值

使用 gson 反序列化时将 TypeToken 转换为 Type 时出错

http请求/restful/序列化反序列化/JSON

将无符号字节流转换为有符号字节流 Golang

将小端序列中的4个字节转换为无符号整数

算法: 把字字符串转化为整数;