Skip to content
2 changes: 1 addition & 1 deletion lib/protobuf/field/bytes_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def coerce!(value)
end
end

def json_encode(value)
def json_encode(value, options={})
Base64.strict_encode64(value)
end
end
Expand Down
7 changes: 7 additions & 0 deletions lib/protobuf/field/int64_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ def acceptable?(val)
return false
end

def json_encode(value, options = {})
if options[:proto3]
value == 0 ? nil : value.to_s
else
value
end
end
end
end
end
7 changes: 7 additions & 0 deletions lib/protobuf/field/sint64_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ def self.min
INT64_MIN
end

def json_encode(value, options = {})
if options[:proto3]
value == 0 ? nil : value.to_s
else
value
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/protobuf/field/string_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def encode(value)
"#{::Protobuf::Field::VarintField.encode(value_to_encode.bytesize)}#{value_to_encode}"
end

def json_encode(value)
def json_encode(value, options={})
value
end
end
Expand Down
7 changes: 7 additions & 0 deletions lib/protobuf/field/uint64_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ def self.min
0
end

def json_encode(value, options = {})
if options[:proto3]
value == 0 ? nil : value.to_s
else
value
end
end
end
end
end
12 changes: 8 additions & 4 deletions lib/protobuf/message.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def to_json(options = {})
def to_json_hash(options = {})
result = {}

lower_camel_case = options[:lower_camel_case]
proto3 = options[:proto3] || options[:lower_camel_case]

@values.each_key do |field_name|
value = self[field_name]
Expand All @@ -153,13 +153,17 @@ def to_json_hash(options = {})
hashed_value = if value.respond_to?(:to_json_hash_value)
value.to_json_hash_value(options)
elsif field.respond_to?(:json_encode)
field.json_encode(value)
field.json_encode(value, options)
else
value
end

key = lower_camel_case ? field.name.to_s.camelize(:lower).to_sym : field.name
result[key] = hashed_value
if proto3 && (hashed_value.nil? || value == field.class.default)
result.delete(field.name)
else
key = proto3 ? field.name.to_s.camelize(:lower).to_sym : field.name
result[key] = hashed_value
end
end

result
Expand Down
26 changes: 26 additions & 0 deletions spec/lib/protobuf/field/fixed64_field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,30 @@

it_behaves_like :packable_field, described_class

let(:message) do
Class.new(::Protobuf::Message) do
optional :fixed64, :some_field, 1
end
end

# https://developers.google.com/protocol-buffers/docs/proto3#json
describe '.{to_json, from_json}' do
it 'serialises 0' do
instance = message.new(some_field: 0)
expect(instance.to_json(proto3: true)).to eq('{}')
expect(instance.to_json).to eq('{"some_field":0}')
end

it 'serialises max value' do
instance = message.new(some_field: described_class.max)
expect(instance.to_json(proto3: true)).to eq('{"someField":"18446744073709551615"}')
expect(instance.to_json).to eq('{"some_field":18446744073709551615}')
end

it 'serialises min value' do
instance = message.new(some_field: described_class.min)
expect(instance.to_json(proto3: true)).to eq('{}')
expect(instance.to_json).to eq('{"some_field":0}')
end
end
end
26 changes: 26 additions & 0 deletions spec/lib/protobuf/field/int64_field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,30 @@

it_behaves_like :packable_field, described_class

let(:message) do
Class.new(::Protobuf::Message) do
optional :int64, :some_field, 1
end
end

# https://developers.google.com/protocol-buffers/docs/proto3#json
describe '.{to_json, from_json}' do
it 'serialises 0' do
instance = message.new(some_field: 0)
expect(instance.to_json(proto3: true)).to eq('{}')
expect(instance.to_json).to eq('{"some_field":0}')
end

it 'serialises max value' do
instance = message.new(some_field: described_class.max)
expect(instance.to_json(proto3: true)).to eq('{"someField":"9223372036854775807"}')
expect(instance.to_json).to eq('{"some_field":9223372036854775807}')
end

it 'serialises min value' do
instance = message.new(some_field: described_class.min)
expect(instance.to_json(proto3: true)).to eq('{"someField":"-9223372036854775808"}')
expect(instance.to_json).to eq('{"some_field":-9223372036854775808}')
end
end
end
26 changes: 26 additions & 0 deletions spec/lib/protobuf/field/sfixed64_field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,30 @@
let(:value) { [-1, 0, 1] }
end

let(:message) do
Class.new(::Protobuf::Message) do
optional :sfixed64, :some_field, 1
end
end

# https://developers.google.com/protocol-buffers/docs/proto3#json
describe '.{to_json, from_json}' do
it 'serialises 0' do
instance = message.new(some_field: 0)
expect(instance.to_json(proto3: true)).to eq('{}')
expect(instance.to_json).to eq('{"some_field":0}')
end

it 'serialises max value' do
instance = message.new(some_field: described_class.max)
expect(instance.to_json(proto3: true)).to eq('{"someField":"9223372036854775807"}')
expect(instance.to_json).to eq('{"some_field":9223372036854775807}')
end

it 'serialises min value as string' do
instance = message.new(some_field: described_class.min)
expect(instance.to_json(proto3: true)).to eq('{"someField":"-9223372036854775808"}')
expect(instance.to_json).to eq('{"some_field":-9223372036854775808}')
end
end
end
26 changes: 26 additions & 0 deletions spec/lib/protobuf/field/sint64_field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,30 @@
let(:value) { [-1, 0, 1] }
end

let(:message) do
Class.new(::Protobuf::Message) do
optional :sint64, :some_field, 1
end
end

# https://developers.google.com/protocol-buffers/docs/proto3#json
describe '.{to_json, from_json}' do
it 'serialises 0' do
instance = message.new(some_field: 0)
expect(instance.to_json(proto3: true)).to eq('{}')
expect(instance.to_json).to eq('{"some_field":0}')
end

it 'serialises max value as string' do
instance = message.new(some_field: described_class.max)
expect(instance.to_json(proto3: true)).to eq('{"someField":"9223372036854775807"}')
expect(instance.to_json).to eq('{"some_field":9223372036854775807}')
end

it 'serialises min value as string' do
instance = message.new(some_field: described_class.min)
expect(instance.to_json(proto3: true)).to eq('{"someField":"-9223372036854775808"}')
expect(instance.to_json).to eq('{"some_field":-9223372036854775808}')
end
end
end
26 changes: 26 additions & 0 deletions spec/lib/protobuf/field/uint64_field_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,30 @@

it_behaves_like :packable_field, described_class

let(:message) do
Class.new(::Protobuf::Message) do
optional :uint64, :some_field, 1
end
end

# https://developers.google.com/protocol-buffers/docs/proto3#json
describe '.{to_json, from_json}' do
it 'serialises 0' do
instance = message.new(some_field: 0)
expect(instance.to_json(proto3: true)).to eq('{}')
expect(instance.to_json).to eq('{"some_field":0}')
end

it 'serialises max value' do
instance = message.new(some_field: described_class.max)
expect(instance.to_json(proto3: true)).to eq('{"someField":"18446744073709551615"}')
expect(instance.to_json).to eq('{"some_field":18446744073709551615}')
end

it 'serialises min value' do
instance = message.new(some_field: described_class.min)
expect(instance.to_json(proto3: true)).to eq('{}')
expect(instance.to_json).to eq('{"some_field":0}')
end
end
end
4 changes: 2 additions & 2 deletions spec/lib/protobuf/message_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -438,14 +438,14 @@
specify { expect(subject.to_json).to eq '{"widget_bytes":["Bo0xSFAXOmI="]}' }
end

context 'using lower camel case field names' do
context 'using proto3 produces lower case field names' do
let(:bytes) { "\x06\x8D1HP\x17:b" }

subject do
::Test::ResourceFindRequest.new(:widget_bytes => [bytes])
end

specify { expect(subject.to_json(:lower_camel_case => true)).to eq '{"widgetBytes":["Bo0xSFAXOmI="]}' }
specify { expect(subject.to_json(:proto3 => true)).to eq '{"widgetBytes":["Bo0xSFAXOmI="]}' }
end
end

Expand Down