Merge pull request #1413 from haberman/updateupb

Updated upb: JSON parser now accepts both camelCase and original case, and flag to choose on output.
This commit is contained in:
Joshua Haberman 2016-04-15 12:57:39 -07:00
commit ca9bbd71d5
9 changed files with 1673 additions and 1405 deletions

View File

@ -80,7 +80,6 @@ JsonInput.Int32FieldMaxFloatValue.JsonOutput
JsonInput.Int32FieldMaxFloatValue.ProtobufOutput
JsonInput.Int32FieldMinFloatValue.JsonOutput
JsonInput.Int32FieldMinFloatValue.ProtobufOutput
JsonInput.Int32FieldMinValue.JsonOutput
JsonInput.Int32FieldStringValue.JsonOutput
JsonInput.Int32FieldStringValue.ProtobufOutput
JsonInput.Int32FieldStringValueEscaped.JsonOutput
@ -125,7 +124,6 @@ JsonInput.OptionalUint64Wrapper.ProtobufOutput
JsonInput.OptionalWrapperTypesWithNonDefaultValue.JsonOutput
JsonInput.OptionalWrapperTypesWithNonDefaultValue.ProtobufOutput
JsonInput.OriginalProtoFieldName.JsonOutput
JsonInput.OriginalProtoFieldName.ProtobufOutput
JsonInput.PrimitiveRepeatedField.JsonOutput
JsonInput.PrimitiveRepeatedField.ProtobufOutput
JsonInput.RepeatedBoolWrapper.JsonOutput

View File

@ -32,23 +32,25 @@ documentation may be found in the RubyDoc comments (`call-seq` tags) in the
source, and we plan to release separate, more detailed, documentation at a
later date.
require 'google/protobuf'
```ruby
require 'google/protobuf'
# generated from my_proto_types.proto with protoc:
# $ protoc --ruby_out=. my_proto_types.proto
require 'my_proto_types'
# generated from my_proto_types.proto with protoc:
# $ protoc --ruby_out=. my_proto_types.proto
require 'my_proto_types'
mymessage = MyTestMessage.new(:field1 => 42, :field2 => ["a", "b", "c"])
mymessage.field1 = 43
mymessage.field2.push("d")
mymessage.field3 = SubMessage.new(:foo => 100)
mymessage = MyTestMessage.new(:field1 => 42, :field2 => ["a", "b", "c"])
mymessage.field1 = 43
mymessage.field2.push("d")
mymessage.field3 = SubMessage.new(:foo => 100)
encoded_data = MyTestMessage.encode(mymessage)
decoded = MyTestMessage.decode(encoded_data)
assert decoded == mymessage
encoded_data = MyTestMessage.encode(mymessage)
decoded = MyTestMessage.decode(encoded_data)
assert decoded == mymessage
puts "JSON:"
puts MyTestMessage.encode_json(mymessage)
puts "JSON:"
puts MyTestMessage.encode_json(mymessage)
```
Installation from Source (Building Gem)
---------------------------------------

View File

@ -255,6 +255,10 @@ void Descriptor_free(void* _self) {
upb_handlers_unref(self->json_serialize_handlers,
&self->json_serialize_handlers);
}
if (self->json_serialize_handlers_preserve) {
upb_handlers_unref(self->json_serialize_handlers_preserve,
&self->json_serialize_handlers_preserve);
}
xfree(self);
}
@ -278,6 +282,7 @@ VALUE Descriptor_alloc(VALUE klass) {
self->json_fill_method = NULL;
self->pb_serialize_handlers = NULL;
self->json_serialize_handlers = NULL;
self->json_serialize_handlers_preserve = NULL;
self->typeclass_references = rb_ary_new();
return ret;
}

View File

@ -1130,13 +1130,23 @@ static const upb_handlers* msgdef_pb_serialize_handlers(Descriptor* desc) {
return desc->pb_serialize_handlers;
}
static const upb_handlers* msgdef_json_serialize_handlers(Descriptor* desc) {
if (desc->json_serialize_handlers == NULL) {
desc->json_serialize_handlers =
upb_json_printer_newhandlers(
desc->msgdef, &desc->json_serialize_handlers);
static const upb_handlers* msgdef_json_serialize_handlers(
Descriptor* desc, bool preserve_proto_fieldnames) {
if (preserve_proto_fieldnames) {
if (desc->json_serialize_handlers == NULL) {
desc->json_serialize_handlers =
upb_json_printer_newhandlers(
desc->msgdef, true, &desc->json_serialize_handlers);
}
return desc->json_serialize_handlers;
} else {
if (desc->json_serialize_handlers_preserve == NULL) {
desc->json_serialize_handlers_preserve =
upb_json_printer_newhandlers(
desc->msgdef, false, &desc->json_serialize_handlers_preserve);
}
return desc->json_serialize_handlers_preserve;
}
return desc->json_serialize_handlers;
}
/*
@ -1181,16 +1191,33 @@ VALUE Message_encode(VALUE klass, VALUE msg_rb) {
*
* Encodes the given message object into its serialized JSON representation.
*/
VALUE Message_encode_json(VALUE klass, VALUE msg_rb) {
VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass) {
VALUE descriptor = rb_ivar_get(klass, descriptor_instancevar_interned);
Descriptor* desc = ruby_to_Descriptor(descriptor);
VALUE msg_rb;
VALUE preserve_proto_fieldnames = Qfalse;
stringsink sink;
if (argc < 1 || argc > 2) {
rb_raise(rb_eArgError, "Expected 1 or 2 arguments.");
}
msg_rb = argv[0];
if (argc == 2) {
VALUE hash_args = argv[1];
if (TYPE(hash_args) != T_HASH) {
rb_raise(rb_eArgError, "Expected hash arguments.");
}
preserve_proto_fieldnames = rb_hash_lookup2(
hash_args, ID2SYM(rb_intern("preserve_proto_fieldnames")), Qfalse);
}
stringsink_init(&sink);
{
const upb_handlers* serialize_handlers =
msgdef_json_serialize_handlers(desc);
msgdef_json_serialize_handlers(desc, RTEST(preserve_proto_fieldnames));
upb_json_printer* printer;
stackenv se;
VALUE ret;

View File

@ -475,7 +475,7 @@ VALUE build_class_from_descriptor(Descriptor* desc) {
rb_define_singleton_method(klass, "decode", Message_decode, 1);
rb_define_singleton_method(klass, "encode", Message_encode, 1);
rb_define_singleton_method(klass, "decode_json", Message_decode_json, 1);
rb_define_singleton_method(klass, "encode_json", Message_encode_json, 1);
rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
return klass;

View File

@ -115,6 +115,7 @@ struct Descriptor {
const upb_json_parsermethod* json_fill_method;
const upb_handlers* pb_serialize_handlers;
const upb_handlers* json_serialize_handlers;
const upb_handlers* json_serialize_handlers_preserve;
// Handlers hold type class references for sub-message fields directly in some
// cases. We need to keep these rooted because they might otherwise be
// collected.
@ -498,7 +499,7 @@ VALUE Message_descriptor(VALUE klass);
VALUE Message_decode(VALUE klass, VALUE data);
VALUE Message_encode(VALUE klass, VALUE msg_rb);
VALUE Message_decode_json(VALUE klass, VALUE data);
VALUE Message_encode_json(VALUE klass, VALUE msg_rb);
VALUE Message_encode_json(int argc, VALUE* argv, VALUE klass);
VALUE Google_Protobuf_deep_copy(VALUE self, VALUE obj);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1161,7 +1161,12 @@ module BasicTest
return if RUBY_PLATFORM == "java"
m = MapMessage.new(:map_string_int32 => {"a" => 1})
expected = '{"mapStringInt32":{"a":1},"mapStringMsg":{}}'
expected_preserve = '{"map_string_int32":{"a":1},"map_string_msg":{}}'
assert MapMessage.encode_json(m) == expected
json = MapMessage.encode_json(m, :preserve_proto_fieldnames => true)
assert json == expected_preserve
m2 = MapMessage.decode_json(MapMessage.encode_json(m))
assert m == m2
end