如何从json表示中获取IPAddr
实例?
我正在使用一个使用draftsman
gem的Rails应用程序。基本上,当一个人对数据库中的记录和ruby模型has_drafts
进行更改时,不会立即对记录进行更改,而是将更改草稿和结果记录保存在草稿表中,直到一个publish!
es草案。然后对实际记录进行更改。非常整洁:)
草稿表保存了允许更改在postgres表中的json列中发生的对象。
我也在使用Devise,我的用户模型使用trackable
模块,其中包含current_sign_in_ip
以及last_sign_in_ip
列类型inet
。
inet
类型列以及User
对象的其余部分存储在由单个json列中的draftsman
gem创建的草稿表中叫object
。由于以下原因,reify
草案中的对象在这种情况下不会成功:IPAddr
个实例具有IPAddr
类无法感知的json表示。例如,ruby中的IPAddr
个实例会回复to_json
,这会给我一些如下所示的内容:"\"family\":2,\"addr\":2130706433,\"mask_addr\":4294967295}"
。这些实例也会回复to_s
并给我这样的内容:"127.0.0.1"
。不幸的是,IPAddr
类似乎不知道如何从我所知道的json中恢复过来:
[277, 286] in /home/jake/.rvm/gems/ruby-2.2.1/bundler/gems/draftsman-1bd3c797d540/lib/draftsman/model.rb
277: data = {
278: :item => self,
279: :whodunnit => Draftsman.whodunnit,
280: :object => object_attrs_for_draft_record
281: }
=> 282: data = merge_metadata_for_draft(data)
283:
284: # If there's already a draft, update it.
285: if send(self.class.draft_association_name).present?
286: data[:object_changes] = changes_for_draftsman if track_object_changes_for_draft?
(byebug) data[:object]['current_sign_in_ip']
#<IPAddr: IPv4:127.0.0.1/255.255.255.255>
(byebug) data[:object]['current_sign_in_ip'].to_json
"{\"family\":2,\"addr\":2130706433,\"mask_addr\":4294967295}"
(byebug) IPAddr.new(data[:object]['current_sign_in_ip'].to_s)
#<IPAddr: IPv4:127.0.0.1/255.255.255.255>
(byebug) IPAddr.new(data[:object]['current_sign_in_ip'].to_json)
*** IPAddr::InvalidAddressError Exception: invalid address
nil
(byebug)
我认为将这个问题发布到StackOverflow会引起一些关注,但如果需要任何其他信息,我还会在Draftsman
github页面上提交一个github issue。
答案 0 :(得分:2)
不确定这是否有帮助,但如果您在d_ethier的回答下面阅读我的评论,您会发现IPAddr
对JSON一无所知。
但是你可以修补它来理解JSON,如下所示:
require 'active_model'
require 'active_support'
require 'active_support/core_ext'
require 'ipaddr'
class IPAddr
include ActiveModel::Serializers::JSON
attr_accessor :addr, :mask_addr, :family
def attributes=(hash)
hash.each do |key, value|
send("#{key}=", value)
end
end
def attributes
instance_values
end
end
p i = IPAddr.new('127.0.0.1')
p j = i.to_json
p IPAddr.new.from_json(j)
输出:
#<IPAddr: IPv4:127.0.0.1/255.255.255.255>
"{\"family\":2,\"addr\":2130706433,\"mask_addr\":4294967295}"
#<IPAddr: IPv4:127.0.0.1/255.255.255.255>
来源:
http://apidock.com/rails/ActiveModel/Serializers/JSON/from_json
答案 1 :(得分:0)
我怀疑这个问题是另一回事。
import net.glxn.qrgen.QRCode;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
public static BufferedImage generate() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
QRCode.from("http://www.stackoverflow.com").writeTo(baos);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
return ImageIO.read(bais);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
并未改变IPAddr.new(data[:object]['current_sign_in_ip'].to_s)
的内容,因此不应该成为&#34;转换&#34;的理由。它回来了。
实际上,data[:object]['current_sign_in_ip']
已经是IPAddr对象。在IPAddr.new中包装它是多余的。
我怀疑您正在尝试做其他事情而这只是您的描述,所以如果没有看到您的代码,就很难提供帮助。
如果是这种情况,您可以通过为原始IPAddr实例创建变量并稍后使用它来解决此问题。
data[:object]['current_sign_in_ip']
答案 2 :(得分:0)
如果有人看到这个,我们在 ActiveSupport 中修复了这个问题
https://github.com/rails/rails/issues/40932 https://github.com/rails/rails/commit/e7d207f02fe8bf6e351de7da106839b0ab14bbea
如果使用 Rails,我们应该可以使用初始化程序来解决这个问题:
class IPAddr
def as_json(options = nil)
to_s
end
end