Ruby Time#to_json作为浮点数 [英] Ruby Time#to_json as a float

查看:99
本文介绍了Ruby Time#to_json作为浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Ruby的json库默认将Time对象转换为Strings

Ruby's json library defaults to converting Time objects to Strings

require 'json'
Time.at(1000).utc.to_json # => "\"1970-01-01 00:16:40 UTC\"" 

问题是我们失去了精度.我想用to_json来生成浮点数.

The problem with this is that we lose precision. I'd like to_json to produce a float instead.

我也知道有一些使用oj或要求使用json/add/time的解决方法,但是这两种方法都会在输出中添加多余的数据,并且不是最可移植的.

I also know there are some workarounds using oj or requiring json/add/time, but both of these add excess data to the output and aren't the most portable.

一种简单的方法是给时间打上补丁,尽管我不喜欢这样做,尤其是对于核心类

A straightforward approach is to monkey patch Time, although I'm not fond of doing that, especially to core classes

class Time
  def to_json(*a)
    self.to_f.to_json(*a)
  end
end

有没有更好的方法?

推荐答案

一种简单的方法是给时间打补丁,尽管我不喜欢这样做,特别是对于核心类

日期没有JSON格式,就JSON而言,它们只是字符串.大多数语言都能理解 ISO 8601 ,这就是Time#to_json的结果.只要Time#to_json继续产生ISO 8601日期时间,您就将保持向后兼容.

There's no JSON format for dates, as far as JSON cares they're just strings. Most languages understand ISO 8601, and that's what Time#to_json produces. So long as Time#to_json continues to produce an ISO 8601 datetime you'll remain backwards compatible.

require 'json'
require 'time'  # for Time#iso8601 and Time.parse

class Time
  def to_json
    return self.iso8601(6).to_json
  end
end

time = Time.at(1000.123456)
puts "Before: #{time.iso8601(6)}"

json_time = Time.at(1000.123456).to_json
puts "As JSON: #{json_time}"

# Demonstrate round tripping.
puts "Round trip: #{Time.parse(JSON.parse(json_time)).iso8601(6)}"

Before: 1969-12-31T16:16:40.123456-08:00
As JSON: "1969-12-31T16:16:40.123456-08:00"
Round trip: 1969-12-31T16:16:40.123456-08:00


如果您不满意全局的猴子修补程序,则可以通过实现around来单独进行猴子修补程序.


If you're not comfortable with monkey patching globally, you can monkey patch in isolation by implementing around.

class Time
  require 'time'
  require 'json'

  def precise_to_json(*args)
    return iso8601(6).to_json(*args)
  end

  alias_method :original_to_json, :to_json
end

module PreciseJson
  def self.around
    # Swap in our precise_to_json as Time#to_json
    Time.class_eval {
      alias_method :to_json, :precise_to_json
    }

    # This block will use Time#precise_to_json as Time#to_json
    yield

  # Always put the original Time#to_json back.
  ensure
    Time.class_eval {
      alias_method :to_json, :original_to_json
    }
  end
end

obj = { 
  time: Time.at(1000.123456),
  string: "Basset Hounds Got Long Ears"
}

puts "Before: #{obj.to_json}"

PreciseJson.around {
  puts "Around: #{obj.to_json}"
}

puts "After: #{obj.to_json}"

begin
  PreciseJson.around {
    raise Exception
  }
rescue Exception
end

puts "After exception: #{obj.to_json}"

Before: {"time":"1969-12-31 16:16:40 -0800","string":"Basset Hounds Got Long Ears"}
Around: {"time":"1969-12-31T16:16:40.123456-08:00","string":"Basset Hounds Got Long Ears"}
After: {"time":"1969-12-31 16:16:40 -0800","string":"Basset Hounds Got Long Ears"}
After exception: {"time":"1969-12-31 16:16:40 -0800","string":"Basset Hounds Got Long Ears"}

这篇关于Ruby Time#to_json作为浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆