jam-cloud/websocket-gateway/lib/jam_websockets/message.rb

72 lines
2.3 KiB
Ruby

require 'json'
require 'protocol_buffers'
require 'protocol_buffers/compiler'
class ProtocolBuffers::Message
def to_json(*args)
json = to_json_ready_object()
json.to_json(*args)
end
def to_json_ready_object()
hash = {}
# simpler version, includes all fields in the output, using the default
# values if unset. also includes empty repeated fields as empty arrays.
# fields.each do |tag, field|
# hash[field.name] = value_for_tag(field.tag)
# end
# prettier output, only includes non-empty repeated fields and set fields
fields.each do |tag, field|
if field.repeated?
value = value_for_tag(field.tag)
hash[field.name] = value unless value.empty?
else
if value_for_tag?(field.tag)
value = value_for_tag(field.tag)
if field.instance_of? ProtocolBuffers::Field::EnumField # if value is enum, resolve string value as ruby const
hash[field.name] = field.value_to_name[value]
else
proxy_class = field.instance_variable_get(:@proxy_class)
if proxy_class.nil?
hash[field.name] = value
else
hash[field.name] = value.to_json_ready_object
end
end
end
end
end
return hash
end
def self.json_create(hash)
# initialize takes a hash of { attribute_name => value } so you can just
# pass the hash into the constructor. but we're supposed to be showing off
# reflection, here. plus, that raises an exception if there is an unknown
# key in the hash.
# new(hash)
message = new
fields.each do |tag, field|
if value = hash[field.name.to_s]
if value.instance_of? Hash # if the value is a Hash, descend down into PB hierachy
inner_class = field.instance_variable_get(:@proxy_class)
value = inner_class.json_create(value)
message.set_value_for_tag(field.tag, value)
elsif field.instance_of? ProtocolBuffers::Field::EnumField # if value is enum, resolve string value as ruby const
message.set_value_for_tag(field.tag, field.instance_variable_get(:@proxy_enum).const_get(value))
else
message.set_value_for_tag(field.tag, value)
end
end
end
message
end
end