在 ruby 中自动投射 JSON 编码数据
Automatically cast JSON coded data in ruby
我的挑战是,在数据库中,JSON 代码存储不整齐。
{'isr_comment':'Test Comment',
'isr_depression_1': '1',
'isr_depression_2': '1'
'isr_depression_3': '1'
'isr_tested': 'true'
}
你看,所有值都定义为字符串,但有些值应该是整数。最好在数据库中已有干净的数据,但我无法控制数据的输入方式。但是我的模型看起来像这样。
class SessionPart < ApplicationRecord
...
serialize :answers, JSON
...
end
反序列化完成后,我也得到了字符串。
@data=
{"isr_Comment"=>"Test Comment",
"isr_depression_1"=>"1",
"isr_depression_2"=>"1",
"isr_depression_3"=>"1",
"isr_tested" => "true"}
但是我需要对这些数据进行一些计算,所以我需要具有有意义类型的所有可能值。
@data=
{"isr_Comment"=>"Test Comment",
"isr_depression_1"=>1,
"isr_depression_2"=>1,
"isr_depression_3"=>1,
"isr_tested" => true}
有没有办法自动投射这样的数据?
您可以将自定义序列化程序传递给 serialize 函数。该自定义序列化程序将使用 JSON 作为源序列化程序并根据您的要求更新值。
class SessionPart < ApplicationRecord
...
serialize :answers, CustomSerializer #CustomSerializer must write 2 class level function named dump & load for serializing and de-serializing respectively
...
end
class CustomSerializer
def self.load(value)
normalize_hash(JSON.load(value))
end
def self.dump(value)
JSON.dump(value)
end
private
def self.normalize_hash hash
return hash unless hash.is_a? Hash
hash.transform_values {|v| normalize(v)}
end
#change this function as per your requirement, Currently it's handling boolean,integer,float & null rule set
def self.normalize(value)
case (value)
when 'true'
true
when 'false'
false
when 'null','nil'
nil
when /\A-?\d+\z/
value.to_i
when /\A-?\d+\.\d+\z/
value.to_f
else
value.is_a?(Hash) ? normalize_hash(value) : value
end
end
end
建议的 CustomSerializer
似乎做得很好,谢谢。我做了一些小调整,以便能够嵌套哈希。
class CustomSerializer
def self.load(value)
normalize_hash(JSON.load(value))
end
def self.dump(value)
JSON.dump(value)
end
private
def self.normalize_hash hash
return hash unless hash.is_a? Hash
hash.transform_values {|v| normalize(v) }
end
#change this function as per your requirement, Currently it's handling boolean,integer,float & null rule set
def self.normalize(value)
case (value)
when 'true'
true
when 'false'
false
when 'null','nil'
nil
when /\A-?\d+\z/
value.to_i
when /\A-?\d+\.\d+\z/
value.to_f
else
value.is_a?(Hash) ? normalize_hash(value) : value
end
end
end
我的挑战是,在数据库中,JSON 代码存储不整齐。
{'isr_comment':'Test Comment',
'isr_depression_1': '1',
'isr_depression_2': '1'
'isr_depression_3': '1'
'isr_tested': 'true'
}
你看,所有值都定义为字符串,但有些值应该是整数。最好在数据库中已有干净的数据,但我无法控制数据的输入方式。但是我的模型看起来像这样。
class SessionPart < ApplicationRecord
...
serialize :answers, JSON
...
end
反序列化完成后,我也得到了字符串。
@data=
{"isr_Comment"=>"Test Comment",
"isr_depression_1"=>"1",
"isr_depression_2"=>"1",
"isr_depression_3"=>"1",
"isr_tested" => "true"}
但是我需要对这些数据进行一些计算,所以我需要具有有意义类型的所有可能值。
@data=
{"isr_Comment"=>"Test Comment",
"isr_depression_1"=>1,
"isr_depression_2"=>1,
"isr_depression_3"=>1,
"isr_tested" => true}
有没有办法自动投射这样的数据?
您可以将自定义序列化程序传递给 serialize 函数。该自定义序列化程序将使用 JSON 作为源序列化程序并根据您的要求更新值。
class SessionPart < ApplicationRecord
...
serialize :answers, CustomSerializer #CustomSerializer must write 2 class level function named dump & load for serializing and de-serializing respectively
...
end
class CustomSerializer
def self.load(value)
normalize_hash(JSON.load(value))
end
def self.dump(value)
JSON.dump(value)
end
private
def self.normalize_hash hash
return hash unless hash.is_a? Hash
hash.transform_values {|v| normalize(v)}
end
#change this function as per your requirement, Currently it's handling boolean,integer,float & null rule set
def self.normalize(value)
case (value)
when 'true'
true
when 'false'
false
when 'null','nil'
nil
when /\A-?\d+\z/
value.to_i
when /\A-?\d+\.\d+\z/
value.to_f
else
value.is_a?(Hash) ? normalize_hash(value) : value
end
end
end
建议的 CustomSerializer
似乎做得很好,谢谢。我做了一些小调整,以便能够嵌套哈希。
class CustomSerializer
def self.load(value)
normalize_hash(JSON.load(value))
end
def self.dump(value)
JSON.dump(value)
end
private
def self.normalize_hash hash
return hash unless hash.is_a? Hash
hash.transform_values {|v| normalize(v) }
end
#change this function as per your requirement, Currently it's handling boolean,integer,float & null rule set
def self.normalize(value)
case (value)
when 'true'
true
when 'false'
false
when 'null','nil'
nil
when /\A-?\d+\z/
value.to_i
when /\A-?\d+\.\d+\z/
value.to_f
else
value.is_a?(Hash) ? normalize_hash(value) : value
end
end
end