我在RoR中遇到了奇怪的行为问题。我有一个Hash,我正在使用to_json()
转换为json,如下所示:
data = Hash.new
# ...
data = data.to_json()
此代码显示在模型类中。基本上,我在保存到数据库时将哈希转换为JSON。问题是,字符串会使用其周围的引号保存到数据库中。例如,保存空哈希会导致:"{}"
。从数据库加载时,引用的字符串无法解析。
如何摆脱报价?
代码是:
def do_before_save
@_data = self.data
self.data = self.data.to_json()
end
编辑:
由于混乱,我展示了我的整个模型课程
require 'json'
class User::User < ActiveRecord::Base
after_find { |user|
user.data = JSON.parse(user.data)
}
after_initialize { |user|
self.data = Hash.new unless self.data
}
before_save :do_before_save
after_save :do_after_save
private
def do_before_save
@_data = self.data
self.data = self.data.to_json()
end
def do_after_save
self.data = @_data
end
end
require 'json'
class User::User < ActiveRecord::Base
after_find { |user|
user.data = JSON.parse(user.data)
}
after_initialize { |user|
self.data = Hash.new unless self.data
}
before_save :do_before_save
after_save :do_after_save
private
def do_before_save
@_data = self.data
self.data = self.data.to_json()
end
def do_after_save
self.data = @_data
end
end
mysql中字段为
data
。
答案 0 :(得分:3)
我愿意赌钱,这是你在同一数据上调用.to_json
两次的结果(不解析它们)。在我制定规则之前,我已经有很多这些问题:“不要像这样有损地改变数据”。
如果您的原始数据为{}
,则首先.to_json
会生成"{}"
。但是如果你再次对它进行jsonify,你会得到"\"{}\""
,因为字符串是一个有效的json数据类型。
我建议你在before_save过滤器中放一个断点,看看第二次调用它的原因和原因。
“call .to_json
两次”是一般性描述,也可能意味着同一对象上有两个后续保存,并且由于self.data
被重新分配,这会导致数据损坏。 (谢谢,@ mudasobwa)
答案 1 :(得分:0)
这取决于您的型号的数据库字段类型。
如果字段是字符串类型(如VARCHAR或TEXT),则应将其存储为字符串(无需删除引号 - 它们没问题)。确保拨打to_json
一次。
如果该字段是Postgres JSON类型,那么您只需将哈希值分配给模型的字段,根本不需要调用to_json
。
答案 2 :(得分:0)
如果要在varchar列中将哈希保存为JSON字符串,则可以使用serialize
来处理数据的编组/解组:
class Thing < ActiveRecord::Base
serialize :foo, JSON
end
确切知道何时在记录的生命周期中转换数据实际上比您的幼稚实现要困难得多。所以不要重新发明轮子。
然而,一个巨大的缺点是无法在DB *中查询数据。如果您使用的是Postgres或MySQL,则可以改为使用允许查询的JSON或JSONB(仅限postgres)列类型。此示例来自Rails指南文档:
# db/migrate/20131220144913_create_events.rb
create_table :events do |t|
t.json 'payload'
end
# app/models/event.rb
class Event < ApplicationRecord
end
# Usage
Event.create(payload: { kind: "user_renamed", change: ["jack", "john"]})
event = Event.first
event.payload # => {"kind"=>"user_renamed", "change"=>["jack", "john"]}
## Query based on JSON document
# The -> operator returns the original JSON type (which might be an object), whereas ->> returns text
Event.where("payload->>'kind' = ?", "user_renamed")
答案 3 :(得分:0)
使用{} .as_json而不是{} .to_json
例如:
a = {}
a.as_json # => {}
a.to_json # => "{}"
http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-as_json