class Zenaton::Services::Serializer

Encoding and decoding ruby objects into Zenaton's json format

Constants

ID_PREFIX

this string prefixs ids that are used to identify objects

KEY_ARRAY
KEY_DATA
KEY_OBJECT
KEY_OBJECT_NAME
KEY_OBJECT_PROPERTIES
KEY_STORE

Public Class Methods

new() click to toggle source
# File lib/zenaton/services/serializer.rb, line 21
def initialize
  @properties = Properties.new
end

Public Instance Methods

decode(json_string) click to toggle source

Decodes Zenaton's format in a valid Ruby object

# File lib/zenaton/services/serializer.rb, line 43
def decode(json_string)
  parsed_json = JSON.parse(json_string)
  @decoded = []
  @encoded = parsed_json.delete(KEY_STORE)
  case parsed_json.keys.first
  when KEY_DATA
    return parsed_json[KEY_DATA]
  when KEY_ARRAY
    return decode_enumerable(parsed_json[KEY_ARRAY])
  when KEY_OBJECT
    id = parsed_json[KEY_OBJECT][ID_PREFIX.length..-1].to_i
    return decode_from_store(id, @encoded[id])
  end
end
encode(data) click to toggle source

Encodes a given ruby object to Zenaton's json format

# File lib/zenaton/services/serializer.rb, line 28
def encode(data)
  @encoded = []
  @decoded = []
  value = {}
  raise ArgumentError, 'Procs cannot be serialized' if data.is_a?(Proc)
  if basic_type?(data)
    value[KEY_DATA] = data
  else
    value[KEY_OBJECT] = encode_to_store(data)
  end
  value[KEY_STORE] = @encoded
  value.to_json
end

Private Instance Methods

basic_type?(data) click to toggle source

rubocop:enable Metrics/MethodLength

# File lib/zenaton/services/serializer.rb, line 61
def basic_type?(data)
  data.is_a?(String) \
    || data.is_a?(Integer) \
    || data.is_a?(Float) \
    || data.is_a?(TrueClass) \
    || data.is_a?(FalseClass) \
    || data.nil?
end
decode_array(id, array) click to toggle source
# File lib/zenaton/services/serializer.rb, line 166
def decode_array(id, array)
  @decoded[id] = object = []
  object.concat(array.map(&method(:decode_element)))
end
decode_element(value) click to toggle source

rubocop:disable Metrics/MethodLength

# File lib/zenaton/services/serializer.rb, line 137
def decode_element(value)
  if store_id?(value)
    id = value[ID_PREFIX.length..-1].to_i
    encoded = @encoded[id]
    decode_from_store(id, encoded)
  elsif value.is_a?(Array)
    decode_legacy_array(value)
  elsif value.is_a?(Hash)
    decode_legacy_hash(value)
  else
    value
  end
end
decode_enumerable(enumerable) click to toggle source

rubocop:enable Metrics/MethodLength

# File lib/zenaton/services/serializer.rb, line 152
def decode_enumerable(enumerable)
  return decode_legacy_array(enumerable) if enumerable.is_a?(Array)
  return decode_legacy_hash(enumerable) if enumerable.is_a?(Hash)
  raise ArgumentError, 'Unknown type'
end
decode_from_store(id, encoded) click to toggle source
# File lib/zenaton/services/serializer.rb, line 179
def decode_from_store(id, encoded)
  decoded = @decoded[id]
  return decoded if decoded
  case encoded[KEY_ARRAY]
  when Array
    decode_array(id, encoded[KEY_ARRAY])
  when Hash
    decode_hash(id, encoded[KEY_ARRAY])
  else
    decode_object(id, encoded)
  end
end
decode_hash(id, hash) click to toggle source
# File lib/zenaton/services/serializer.rb, line 171
def decode_hash(id, hash)
  @decoded[id] = ActiveSupport::HashWithIndifferentAccess.new
  hash.each do |key, value|
    @decoded[id][key] = decode_element(value)
  end
  @decoded[id]
end
decode_legacy_array(array) click to toggle source
# File lib/zenaton/services/serializer.rb, line 158
def decode_legacy_array(array)
  array.map(&method(:decode_element))
end
decode_legacy_hash(hash) click to toggle source
# File lib/zenaton/services/serializer.rb, line 162
def decode_legacy_hash(hash)
  transform_values(hash, &method(:decode_element))
end
decode_object(id, encoded_object) click to toggle source
# File lib/zenaton/services/serializer.rb, line 204
def decode_object(id, encoded_object)
  object = @properties.blank_instance(encoded_object[KEY_OBJECT_NAME])
  @decoded[id] = object
  properties = decode_legacy_hash(encoded_object[KEY_OBJECT_PROPERTIES])
  @properties.set(object, properties)
end
decoded_object_by_type(id, encoded) click to toggle source
# File lib/zenaton/services/serializer.rb, line 192
def decoded_object_by_type(id, encoded)
  enumerable = encoded[KEY_ARRAY]
  case enumerable
  when Array
    decode_array(id, enumerable)
  when Hash
    decode_hash(id, enumerable)
  else
    decode_object(id, encoded)
  end
end
encode_array(array) click to toggle source
# File lib/zenaton/services/serializer.rb, line 114
def encode_array(array)
  {
    KEY_ARRAY => array.map(&method(:encode_value))
  }
end
encode_hash(hash) click to toggle source
# File lib/zenaton/services/serializer.rb, line 120
def encode_hash(hash)
  {
    KEY_ARRAY => transform_values(hash, &method(:encode_value))
  }
end
encode_legacy_hash(hash) click to toggle source
# File lib/zenaton/services/serializer.rb, line 126
def encode_legacy_hash(hash)
  transform_values(hash, &method(:encode_value))
end
encode_object(object) click to toggle source
# File lib/zenaton/services/serializer.rb, line 107
def encode_object(object)
  {
    KEY_OBJECT_NAME => object.class.name,
    KEY_OBJECT_PROPERTIES => encode_legacy_hash(@properties.from(object))
  }
end
encode_to_store(object) click to toggle source
# File lib/zenaton/services/serializer.rb, line 79
def encode_to_store(object)
  id = @decoded.index { |decoded| decoded.object_id == object.object_id }
  return store_id(id) if id
  store_and_encode(object)
end
encode_value(value) click to toggle source
# File lib/zenaton/services/serializer.rb, line 70
def encode_value(value)
  raise ArgumentError, 'Procs cannot be serialized' if value.is_a?(Proc)
  if basic_type?(value)
    value
  else
    encode_to_store(value)
  end
end
encoded_object_by_type(object) click to toggle source
# File lib/zenaton/services/serializer.rb, line 96
def encoded_object_by_type(object)
  case object
  when Array
    encode_array(object)
  when Hash
    encode_hash(object)
  else
    encode_object(object)
  end
end
store_and_encode(object) click to toggle source
# File lib/zenaton/services/serializer.rb, line 85
def store_and_encode(object)
  id = @decoded.length
  @decoded[id] = object
  @encoded[id] = encoded_object_by_type(object)
  store_id(id)
end
store_id(id) click to toggle source
# File lib/zenaton/services/serializer.rb, line 92
def store_id(id)
  "#{ID_PREFIX}#{id}"
end
store_id?(string) click to toggle source
# File lib/zenaton/services/serializer.rb, line 130
def store_id?(string)
  string.is_a?(String) \
    && string.start_with?(ID_PREFIX) \
    && string[ID_PREFIX.length..-1].to_i <= @encoded.length
end
transform_values(hash) { |v| ... } click to toggle source
# File lib/zenaton/services/serializer.rb, line 211
def transform_values(hash)
  hash.each_with_object({}) do |(k, v), acc|
    acc[k] = yield(v)
  end
end