2012-09-03 02:45:18 +00:00
|
|
|
require 'json'
|
|
|
|
|
require 'protocol_buffers'
|
|
|
|
|
require 'protocol_buffers/compiler'
|
|
|
|
|
|
|
|
|
|
class ProtocolBuffers::Message
|
|
|
|
|
|
|
|
|
|
def to_json(*args)
|
2012-09-04 01:22:46 +00:00
|
|
|
|
|
|
|
|
json = to_json_ready_object()
|
|
|
|
|
|
|
|
|
|
json.to_json(*args)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def to_json_ready_object()
|
|
|
|
|
hash = {}
|
2012-09-03 02:45:18 +00:00
|
|
|
|
|
|
|
|
# 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
|
2012-09-04 01:22:46 +00:00
|
|
|
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
|
2012-09-03 02:45:18 +00:00
|
|
|
end
|
|
|
|
|
end
|
2012-09-04 01:22:46 +00:00
|
|
|
|
|
|
|
|
return hash
|
2012-09-03 02:45:18 +00:00
|
|
|
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]
|
2012-09-04 01:22:46 +00:00
|
|
|
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
|
2012-09-03 02:45:18 +00:00
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
message
|
|
|
|
|
end
|
|
|
|
|
end
|