rails json.parse“意想不到的令牌”错误
我有一个由Webhooks击中的简单控制器。我需要将发送的所有数据存储在模型的元数据
中,该数据是text
列以供以后消耗。
class NotificationsController < ApplicationController
def create
notification = Notification.new(
metadata: params,
)
if notification.save
head :ok
end
end
end
当我在任何控制器操作中检查params.class
时,我会得到actionController ::参数
像哈希一样的对象。
但是,当在元数据
中存储params
,如上所示,我得到了一个看起来像这样的字符串:
"{\"SmsSid\"=>\"ID\", \"SmsStatus\"=>\"STATUS\",\"controller\"=>\"notifications\", \"action\"=>\"create\"}"
我尝试将该字符串转换回Hash,但是执行json.parse(params)
引发以下错误:
JSON::ParserError: 783: unexpected token at "{\"SmsSid\"=>\"ID\", \"SmsStatus\"=>\"STATUS\",\"controller\"=>\"notifications\", \"action\"=>\"create\"}"
这是因为列类型是text
而不是jsonb
?如果是这样,是否有任何不涉及数据库迁移以更改列类型的解决方法?
I have a simple controller that is hit by webhooks. I need to store all data sent in a model's metadata
which is a text
column for later consumption.
class NotificationsController < ApplicationController
def create
notification = Notification.new(
metadata: params,
)
if notification.save
head :ok
end
end
end
When I inspect params.class
inside any controller action, I get an ActionController::Parameters
object that acts like a hash.
However, when storing params
in the metadata
as shown above, I get a string that looks like this:
"{\"SmsSid\"=>\"ID\", \"SmsStatus\"=>\"STATUS\",\"controller\"=>\"notifications\", \"action\"=>\"create\"}"
I tried converting that string back to a hash, but doing JSON.parse(params)
throws the following error:
JSON::ParserError: 783: unexpected token at "{\"SmsSid\"=>\"ID\", \"SmsStatus\"=>\"STATUS\",\"controller\"=>\"notifications\", \"action\"=>\"create\"}"
Is this because the column type is text
and not jsonb
? If so, is there any workaround that does not involve a DB migration to change the column type?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,这是
params
是什么。这是一个对象,在大多数方面都像hash
。是的,因为您要栏杆采取不像字符串的东西,然后将其转换为字符串,以便可以将其存储在
文本
列。 Rails通过在对象上调用.to_s
来完成此操作,该对象返回您在此处看到的字符串表示。该字符串不是JSON。如果要序列化
params
hash to json,则可以使用序列化api 定义列应如何序列化,然后保存 params的一些安全子集:之后,您可以访问
notification.params
,它将为您透明地进行序列化。请注意,只需将整个不动力的
参数
对象丢入数据库中,这是允许攻击者用千兆字节的垃圾文本淹没数据库的好方法。您绝不应该假设params
是安全的;仅处理您期望的参数
的子集,并确保关联的值符合您的期望。只需使用params.parmit(...)
,就像我上面所做的那样,仍然不够,因为值可能很长,或包含任意垃圾。您应该在模型上使用验证器来执行长度和格式限制。Yes, this is what
params
is. It's an object, that acts like ahash
in most respects.Yes, because you're asking Rails to take something that is not a string, and convert it to a string so it can be stored in a
text
column. Rails does this by calling.to_s
on the object, which returns the string representation you're seeing here.That string isn't JSON. If you want to serialize the
params
hash to JSON, you can use the serialization API to define how the column should be serialized, and then save some safe subset of params:Afterwards, you can access
notification.params
and it will be transparently deserialized for you.Note that simply dumping the entire unsanitized
params
object into your database is a great way to allow attackers to flood your database with gigabytes of garbage text. You should never assume thatparams
is safe; only work with a subset ofparams
that you expect, and make sure the associated values conform to your expectations. Simply usingparams.permit(...)
as I've done above is still not sufficient, as the values could be extremely long, or contain arbitrary garbage. You should use validators on your model to enforce length and format restrictions.我认为将数据存储为JSON字符串可以解决问题。这样:
然后:
或者,如果不想在任何地方写上述代码,您可以覆盖元数据getter方法
I think storing the data as json string can solve the problem. like this:
Then:
or you can override the metadata getter method if don't want to write the above code everywhere