module Xon

Constants

PREAMBLE
VERSION

Public Class Methods

dump(data)
Alias for: generate
generate(data) click to toggle source
# File lib/xon.rb, line 25
def generate(data)
  init!
  if special?(data)
    PREAMBLE + JSON.generate(encode(data))
  else
    JSON.generate(data)
  end
end
Also aliased as: dump
load(str)
Alias for: parse
parse(str) click to toggle source
# File lib/xon.rb, line 14
def parse(str)
  init!
  if str.is_a?(String) && str.start_with?(PREAMBLE)
    decode(JSON.parse(str[PREAMBLE.length..-1]))
  else
    JSON.parse(str)
  end
rescue JSON::ParserError => e
  raise ParserError.new(e.message)
end
Also aliased as: load

Private Class Methods

decode(obj) click to toggle source
# File lib/xon.rb, line 39
def decode(obj)
  if obj.is_a?(String)
    type, value = obj.split(":", 2)
    raise ParserError.new("incorrectly formatted string value") if value.nil?
    case type
    when ''
      value
    when 't'
      begin
        Time.parse(value)
      rescue ArgumentError => e
        raise ParserError.new(e.message)
      end
    else
      raise ParserError.new("unknown type in string value")
    end
  elsif obj.is_a?(Array)
    obj.map { |v| decode(v) }
  elsif obj.is_a?(Hash)
    obj.transform_values { |v| decode(v) }
  else
    obj
  end
end
encode(obj) click to toggle source
# File lib/xon.rb, line 64
def encode(obj)
  if obj.is_a?(String)
    ":#{obj}"
  elsif obj.is_a?(Time) || obj.is_a?(DateTime)
    "t:#{obj.iso8601}"
  elsif obj.is_a?(Array)
    obj.map { |v| encode(v) }
  elsif obj.is_a?(Hash)
    obj.transform_values { |v| encode(v) }
  else
    obj
  end
end
init!() click to toggle source
# File lib/xon.rb, line 93
def init!
  return if @@inited
  @@inited = true
  # Prefer MultiJson if it is loaded.
  const_set(:JSON, defined?(MultiJson) ? MultiJson : JSON)
end
special?(obj) click to toggle source
# File lib/xon.rb, line 78
def special?(obj)
  if obj.is_a?(Time) || obj.is_a?(DateTime)
    true
  elsif obj.is_a?(Array)
    obj.any? { |v| special?(v) }
  elsif obj.is_a?(Hash)
    obj.values.any? { |v| special?(v) }
  else
    false
  end
end