I found that using snake_case in protobuf definition will have slightly different generated method/class names across different languages. The difference is in the casing if the protocol field name uses snake_case.
Example
A regular protoc code-generation based on the following protocol
syntax = "proto3";
package myservice;
service Myservice {
rpc MyService(Request) returns (Reply) {}
}
message Request {
bool my_foo = 1;
bool my_bar = 2;
}
message Reply {
bool is_succeeded = 1;
}
yields the following generated naming
Python
python -m grpc_tools.protoc -I="${SRC_DIR}" --python_out="${DST_DIR}" --grpc_python_out=$DST_DIR --proto_path="${SRC_DIR}" my.proto
my_pb2_grpc.py
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc
import my_pb2 as my__pb2
class MyserviceStub(object):
"""Missing associated documentation comment in .proto file."""
def __init__(self, channel):
"""Constructor.
Args:
channel: A grpc.Channel.
"""
self.MyService = channel.unary_unary(
'/myservice.Myservice/MyService',
request_serializer=my__pb2.Request.SerializeToString,
response_deserializer=my__pb2.Reply.FromString,
)
class MyserviceServicer(object):
"""Missing associated documentation comment in .proto file."""
def MyService(self, request, context):
"""Missing associated documentation comment in .proto file."""
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
context.set_details('Method not implemented!')
raise NotImplementedError('Method not implemented!')
def add_MyserviceServicer_to_server(servicer, server):
rpc_method_handlers = {
'MyService': grpc.unary_unary_rpc_method_handler(
servicer.MyService,
request_deserializer=my__pb2.Request.FromString,
response_serializer=my__pb2.Reply.SerializeToString,
),
}
generic_handler = grpc.method_handlers_generic_handler(
'myservice.Myservice', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
# This class is part of an EXPERIMENTAL API.
class Myservice(object):
"""Missing associated documentation comment in .proto file."""
#staticmethod
def MyService(request,
target,
options=(),
channel_credentials=None,
call_credentials=None,
insecure=False,
compression=None,
wait_for_ready=None,
timeout=None,
metadata=None):
return grpc.experimental.unary_unary(request, target, '/myservice.Myservice/MyService',
my__pb2.Request.SerializeToString,
my__pb2.Reply.FromString,
options, channel_credentials,
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
my_pb2.py
# -*- coding: utf-8 -*-
# Generated by the protocol buffer compiler. DO NOT EDIT!
# source: my.proto
"""Generated protocol buffer code."""
from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
# ##protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
DESCRIPTOR = _descriptor.FileDescriptor(
name='my.proto',
package='myservice',
syntax='proto3',
serialized_options=None,
create_key=_descriptor._internal_create_key,
serialized_pb=b'\n\x08my.proto\x12\tmyservice\")\n\x07Request\x12\x0e\n\x06my_foo\x18\x01 \x01(\x08\x12\x0e\n\x06my_bar\x18\x02 \x01(\x08\"\x1d\n\x05Reply\x12\x14\n\x0cis_succeeded\x18\x01 \x01(\x08\x32#\n\tMyservice\x12\x33\n\tMyService\x12\x12.myservice.Request\x1a\x10.myservice.Reply\"\x00\x62\x06proto3'
)
_REQUEST = _descriptor.Descriptor(
name='Request',
full_name='myservice.Request',
filename=None,
file=DESCRIPTOR,
containing_type=None,
create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='my_foo', full_name='myservice.Request.my_foo', index=0,
number=1, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
_descriptor.FieldDescriptor(
name='my_bar', full_name='myservice.Request.my_bar', index=1,
number=2, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=23,
serialized_end=64,
)
_REPLY = _descriptor.Descriptor(
name='Reply',
full_name='myservice.Reply',
filename=None,
file=DESCRIPTOR,
containing_type=None,
create_key=_descriptor._internal_create_key,
fields=[
_descriptor.FieldDescriptor(
name='is_succeeded', full_name='myservice.Reply.is_succeeded', index=0,
number=1, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None,
serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
],
extensions=[
],
nested_types=[],
enum_types=[
],
serialized_options=None,
is_extendable=False,
syntax='proto3',
extension_ranges=[],
oneofs=[
],
serialized_start=66,
serialized_end=95,
)
DESCRIPTOR.message_types_by_name['Request'] = _REQUEST
DESCRIPTOR.message_types_by_name['Reply'] = _REPLY
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
Request = _reflection.GeneratedProtocolMessageType('Request', (_message.Message,), {
'DESCRIPTOR' : _REQUEST,
'__module__' : 'my_pb2'
# ##protoc_insertion_point(class_scope:myservice.Request)
})
_sym_db.RegisterMessage(Request)
Reply = _reflection.GeneratedProtocolMessageType('Reply', (_message.Message,), {
'DESCRIPTOR' : _REPLY,
'__module__' : 'my_pb2'
# ##protoc_insertion_point(class_scope:myservice.Reply)
})
_sym_db.RegisterMessage(Reply)
_MYSERVICE = _descriptor.ServiceDescriptor(
name='Myservice',
full_name='myservice.Myservice',
file=DESCRIPTOR,
index=0,
serialized_options=None,
create_key=_descriptor._internal_create_key,
serialized_start=97,
serialized_end=161,
methods=[
_descriptor.MethodDescriptor(
name='MyService',
full_name='myservice.Myservice.MyService',
index=0,
containing_service=None,
input_type=_REQUEST,
output_type=_REPLY,
serialized_options=None,
create_key=_descriptor._internal_create_key,
),
])
_sym_db.RegisterServiceDescriptor(_MYSERVICE)
DESCRIPTOR.services_by_name['Myservice'] = _MYSERVICE
# ##protoc_insertion_point(module_scope)
Node.js
With grpc-node the result looks like this
grpc_tools_node_protoc --js_out=import_style=commonjs,binary:"${DST_DIR}" --grpc_out=grpc_js:"${DST_DIR}" --proto_path="${SRC_DIR}" my.proto
my_grpc_pb.js
// GENERATED CODE -- DO NOT EDIT!
'use strict';
var grpc = require('#grpc/grpc-js');
var my_pb = require('./my_pb.js');
function serialize_myservice_Reply(arg) {
if (!(arg instanceof my_pb.Reply)) {
throw new Error('Expected argument of type myservice.Reply');
}
return Buffer.from(arg.serializeBinary());
}
function deserialize_myservice_Reply(buffer_arg) {
return my_pb.Reply.deserializeBinary(new Uint8Array(buffer_arg));
}
function serialize_myservice_Request(arg) {
if (!(arg instanceof my_pb.Request)) {
throw new Error('Expected argument of type myservice.Request');
}
return Buffer.from(arg.serializeBinary());
}
function deserialize_myservice_Request(buffer_arg) {
return my_pb.Request.deserializeBinary(new Uint8Array(buffer_arg));
}
var MyserviceService = exports.MyserviceService = {
myService: {
path: '/myservice.Myservice/MyService',
requestStream: false,
responseStream: false,
requestType: my_pb.Request,
responseType: my_pb.Reply,
requestSerialize: serialize_myservice_Request,
requestDeserialize: deserialize_myservice_Request,
responseSerialize: serialize_myservice_Reply,
responseDeserialize: deserialize_myservice_Reply,
},
};
exports.MyserviceClient = grpc.makeGenericClientConstructor(MyserviceService);
my_pb.js
// source: my.proto
/**
* #fileoverview
* #enhanceable
* #suppress {missingRequire} reports error on implicit type usages.
* #suppress {messageConventions} JS Compiler reports an error if a variable or
* field starts with 'MSG_' and isn't a translatable message.
* #public
*/
// GENERATED CODE -- DO NOT EDIT!
/* eslint-disable */
// #ts-nocheck
var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();
goog.exportSymbol('proto.myservice.Reply', null, global);
goog.exportSymbol('proto.myservice.Request', null, global);
/**
* Generated by JsPbCodeGenerator.
* #param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* #extends {jspb.Message}
* #constructor
*/
proto.myservice.Request = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.myservice.Request, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* #public
* #override
*/
proto.myservice.Request.displayName = 'proto.myservice.Request';
}
/**
* Generated by JsPbCodeGenerator.
* #param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* #extends {jspb.Message}
* #constructor
*/
proto.myservice.Reply = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.myservice.Reply, jspb.Message);
if (goog.DEBUG && !COMPILED) {
/**
* #public
* #override
*/
proto.myservice.Reply.displayName = 'proto.myservice.Reply';
}
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* #param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* #return {!Object}
*/
proto.myservice.Request.prototype.toObject = function(opt_includeInstance) {
return proto.myservice.Request.toObject(opt_includeInstance, this);
};
/**
* Static version of the {#see toObject} method.
* #param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* #param {!proto.myservice.Request} msg The msg instance to transform.
* #return {!Object}
* #suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.myservice.Request.toObject = function(includeInstance, msg) {
var f, obj = {
myFoo: jspb.Message.getBooleanFieldWithDefault(msg, 1, false),
myBar: jspb.Message.getBooleanFieldWithDefault(msg, 2, false)
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* #param {jspb.ByteSource} bytes The bytes to deserialize.
* #return {!proto.myservice.Request}
*/
proto.myservice.Request.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.myservice.Request;
return proto.myservice.Request.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* #param {!proto.myservice.Request} msg The message object to deserialize into.
* #param {!jspb.BinaryReader} reader The BinaryReader to use.
* #return {!proto.myservice.Request}
*/
proto.myservice.Request.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** #type {boolean} */ (reader.readBool());
msg.setMyFoo(value);
break;
case 2:
var value = /** #type {boolean} */ (reader.readBool());
msg.setMyBar(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* #return {!Uint8Array}
*/
proto.myservice.Request.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.myservice.Request.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* #param {!proto.myservice.Request} message
* #param {!jspb.BinaryWriter} writer
* #suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.myservice.Request.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getMyFoo();
if (f) {
writer.writeBool(
1,
f
);
}
f = message.getMyBar();
if (f) {
writer.writeBool(
2,
f
);
}
};
/**
* optional bool my_foo = 1;
* #return {boolean}
*/
proto.myservice.Request.prototype.getMyFoo = function() {
return /** #type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));
};
/**
* #param {boolean} value
* #return {!proto.myservice.Request} returns this
*/
proto.myservice.Request.prototype.setMyFoo = function(value) {
return jspb.Message.setProto3BooleanField(this, 1, value);
};
/**
* optional bool my_bar = 2;
* #return {boolean}
*/
proto.myservice.Request.prototype.getMyBar = function() {
return /** #type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 2, false));
};
/**
* #param {boolean} value
* #return {!proto.myservice.Request} returns this
*/
proto.myservice.Request.prototype.setMyBar = function(value) {
return jspb.Message.setProto3BooleanField(this, 2, value);
};
if (jspb.Message.GENERATE_TO_OBJECT) {
/**
* Creates an object representation of this proto.
* Field names that are reserved in JavaScript and will be renamed to pb_name.
* Optional fields that are not set will be set to undefined.
* To access a reserved field use, foo.pb_<name>, eg, foo.pb_default.
* For the list of reserved names please see:
* net/proto2/compiler/js/internal/generator.cc#kKeyword.
* #param {boolean=} opt_includeInstance Deprecated. whether to include the
* JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* #return {!Object}
*/
proto.myservice.Reply.prototype.toObject = function(opt_includeInstance) {
return proto.myservice.Reply.toObject(opt_includeInstance, this);
};
/**
* Static version of the {#see toObject} method.
* #param {boolean|undefined} includeInstance Deprecated. Whether to include
* the JSPB instance for transitional soy proto support:
* http://goto/soy-param-migration
* #param {!proto.myservice.Reply} msg The msg instance to transform.
* #return {!Object}
* #suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.myservice.Reply.toObject = function(includeInstance, msg) {
var f, obj = {
isSucceeded: jspb.Message.getBooleanFieldWithDefault(msg, 1, false)
};
if (includeInstance) {
obj.$jspbMessageInstance = msg;
}
return obj;
};
}
/**
* Deserializes binary data (in protobuf wire format).
* #param {jspb.ByteSource} bytes The bytes to deserialize.
* #return {!proto.myservice.Reply}
*/
proto.myservice.Reply.deserializeBinary = function(bytes) {
var reader = new jspb.BinaryReader(bytes);
var msg = new proto.myservice.Reply;
return proto.myservice.Reply.deserializeBinaryFromReader(msg, reader);
};
/**
* Deserializes binary data (in protobuf wire format) from the
* given reader into the given message object.
* #param {!proto.myservice.Reply} msg The message object to deserialize into.
* #param {!jspb.BinaryReader} reader The BinaryReader to use.
* #return {!proto.myservice.Reply}
*/
proto.myservice.Reply.deserializeBinaryFromReader = function(msg, reader) {
while (reader.nextField()) {
if (reader.isEndGroup()) {
break;
}
var field = reader.getFieldNumber();
switch (field) {
case 1:
var value = /** #type {boolean} */ (reader.readBool());
msg.setIsSucceeded(value);
break;
default:
reader.skipField();
break;
}
}
return msg;
};
/**
* Serializes the message to binary data (in protobuf wire format).
* #return {!Uint8Array}
*/
proto.myservice.Reply.prototype.serializeBinary = function() {
var writer = new jspb.BinaryWriter();
proto.myservice.Reply.serializeBinaryToWriter(this, writer);
return writer.getResultBuffer();
};
/**
* Serializes the given message to binary data (in protobuf wire
* format), writing to the given BinaryWriter.
* #param {!proto.myservice.Reply} message
* #param {!jspb.BinaryWriter} writer
* #suppress {unusedLocalVariables} f is only used for nested messages
*/
proto.myservice.Reply.serializeBinaryToWriter = function(message, writer) {
var f = undefined;
f = message.getIsSucceeded();
if (f) {
writer.writeBool(
1,
f
);
}
};
/**
* optional bool is_succeeded = 1;
* #return {boolean}
*/
proto.myservice.Reply.prototype.getIsSucceeded = function() {
return /** #type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 1, false));
};
/**
* #param {boolean} value
* #return {!proto.myservice.Reply} returns this
*/
proto.myservice.Reply.prototype.setIsSucceeded = function(value) {
return jspb.Message.setProto3BooleanField(this, 1, value);
};
goog.object.extend(exports, proto.myservice);
Dart
With the same treatment as above
protoc --plugin=protoc-gen-dart="$HOME/.pub-cache/bin/protoc-gen-dart" --dart_out=grpc:"${DST_DIR}" -I"${SRC_DIR}" -I"$IncludeDir" my.proto
my.pbgrpc.dart
///
// Generated code. Do not modify.
// source: my.proto
//
// #dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
import 'dart:async' as $async;
import 'dart:core' as $core;
import 'package:grpc/service_api.dart' as $grpc;
import 'my.pb.dart' as $0;
export 'my.pb.dart';
class MyserviceClient extends $grpc.Client {
static final _$myService = $grpc.ClientMethod<$0.Request, $0.Reply>(
'/myservice.Myservice/MyService',
($0.Request value) => value.writeToBuffer(),
($core.List<$core.int> value) => $0.Reply.fromBuffer(value));
MyserviceClient($grpc.ClientChannel channel,
{$grpc.CallOptions? options,
$core.Iterable<$grpc.ClientInterceptor>? interceptors})
: super(channel, options: options, interceptors: interceptors);
$grpc.ResponseFuture<$0.Reply> myService($0.Request request,
{$grpc.CallOptions? options}) {
return $createUnaryCall(_$myService, request, options: options);
}
}
abstract class MyserviceServiceBase extends $grpc.Service {
$core.String get $name => 'myservice.Myservice';
MyserviceServiceBase() {
$addMethod($grpc.ServiceMethod<$0.Request, $0.Reply>(
'MyService',
myService_Pre,
false,
false,
($core.List<$core.int> value) => $0.Request.fromBuffer(value),
($0.Reply value) => value.writeToBuffer()));
}
$async.Future<$0.Reply> myService_Pre(
$grpc.ServiceCall call, $async.Future<$0.Request> request) async {
return myService(call, await request);
}
$async.Future<$0.Reply> myService($grpc.ServiceCall call, $0.Request request);
}
my.pb.dart
///
// Generated code. Do not modify.
// source: my.proto
//
// #dart = 2.12
// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
import 'dart:core' as $core;
import 'package:protobuf/protobuf.dart' as $pb;
class Request extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Request', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'myservice'), createEmptyInstance: create)
..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'myFoo')
..aOB(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'myBar')
..hasRequiredFields = false
;
Request._() : super();
factory Request({
$core.bool? myFoo,
$core.bool? myBar,
}) {
final _result = create();
if (myFoo != null) {
_result.myFoo = myFoo;
}
if (myBar != null) {
_result.myBar = myBar;
}
return _result;
}
factory Request.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory Request.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
#$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
Request clone() => Request()..mergeFromMessage(this);
#$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
Request copyWith(void Function(Request) updates) => super.copyWith((message) => updates(message as Request)) as Request; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
#$core.pragma('dart2js:noInline')
static Request create() => Request._();
Request createEmptyInstance() => create();
static $pb.PbList<Request> createRepeated() => $pb.PbList<Request>();
#$core.pragma('dart2js:noInline')
static Request getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Request>(create);
static Request? _defaultInstance;
#$pb.TagNumber(1)
$core.bool get myFoo => $_getBF(0);
#$pb.TagNumber(1)
set myFoo($core.bool v) { $_setBool(0, v); }
#$pb.TagNumber(1)
$core.bool hasMyFoo() => $_has(0);
#$pb.TagNumber(1)
void clearMyFoo() => clearField(1);
#$pb.TagNumber(2)
$core.bool get myBar => $_getBF(1);
#$pb.TagNumber(2)
set myBar($core.bool v) { $_setBool(1, v); }
#$pb.TagNumber(2)
$core.bool hasMyBar() => $_has(1);
#$pb.TagNumber(2)
void clearMyBar() => clearField(2);
}
class Reply extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Reply', package: const $pb.PackageName(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'myservice'), createEmptyInstance: create)
..aOB(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'isSucceeded')
..hasRequiredFields = false
;
Reply._() : super();
factory Reply({
$core.bool? isSucceeded,
}) {
final _result = create();
if (isSucceeded != null) {
_result.isSucceeded = isSucceeded;
}
return _result;
}
factory Reply.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
factory Reply.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
#$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
'Will be removed in next major version')
Reply clone() => Reply()..mergeFromMessage(this);
#$core.Deprecated(
'Using this can add significant overhead to your binary. '
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
'Will be removed in next major version')
Reply copyWith(void Function(Reply) updates) => super.copyWith((message) => updates(message as Reply)) as Reply; // ignore: deprecated_member_use
$pb.BuilderInfo get info_ => _i;
#$core.pragma('dart2js:noInline')
static Reply create() => Reply._();
Reply createEmptyInstance() => create();
static $pb.PbList<Reply> createRepeated() => $pb.PbList<Reply>();
#$core.pragma('dart2js:noInline')
static Reply getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Reply>(create);
static Reply? _defaultInstance;
#$pb.TagNumber(1)
$core.bool get isSucceeded => $_getBF(0);
#$pb.TagNumber(1)
set isSucceeded($core.bool v) { $_setBool(0, v); }
#$pb.TagNumber(1)
$core.bool hasIsSucceeded() => $_has(0);
#$pb.TagNumber(1)
void clearIsSucceeded() => clearField(1);
}
Comparison
If we compare the following generated entities
Service class name
Service method name
Request field names
Reply field names
Here are the results
Python
Myservice
MyService
my_foo
my_bar
is_succeeded
Node.js
MyserviceService
myService
accessor: getMyFoo()
accessor: getMyBar()
accessor: getIsSucceeded()
Dart
MyserviceServiceBase
myService
myFoo
myBar
isSucceeded
Question
Although these naming schemes seem to cater to the language-specific convention,
the differences between them caused some maintenance issues.
I wonder if there is a way to ensure an identical casing treatment across all these languages, and possibly all supported languages.
Thanks!
Code generation plugins have complete freedom to generate whatever code they want. Usually, they try to follow the language's conventions. You'd need to have controls for each language, and most won't provide it.
What are the actual maintenance issues that you are facing? Perhaps there is some other way of solving them.
I am trying to create a room availability script for a conference room at my university. I decided to achieve it using jQuery by parsing a JSON feed of a public Google calendar and then displaying on the screen whether room is available or not.
I feel stupid, I have been fighting this problems for 3 days and no matter whether there is an appointment in Google calendar or not the script says that room is available. Could anyone offer a suggestion why this may be happening. I am not a programmer and I bet this is something really simple but I just can't seem to see it. Any help would be greatly appreciated!
A minimal working example on jsFiddle and below:
<html>
<head>
<title>Graduate Center Conference Room</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script>
// Declare global variables
var events = [];
var currentReservation = null;
var nextReservation = null;
var gclaData = 'http://www.google.com/calendar/feeds/4occ2bc4m626a3pgmirlm06q5s%40group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&futureevents=true&singleevents=true&max-results=2&alt=json';
// Parse Google Calendar Public JSON Feed and store in the events global array
$(document).ready(function () {
$.getJSON(gclaData, function (data) {
$.each(data.feed.entry, function (i, entry) {
var dtStart = new Date(entry["gd$when"][0].startTime);
var dtEnd = new Date(entry["gd$when"][0].endTime);
var dtSummary = entry.content.$t;
var dtTitle = entry.title.$t;
events[i] = {
'start': dtStart,
'end': dtEnd,
'title': dtTitle,
'summary': dtSummary
};
});
});
reservationInfo = '';
// sort events just in case (JSON should be sorted anyways)
events.sort(function (a, b) {
return a.start - b.start;
});
// current date
var dtNow = new Date();
// let's assume there are no current room reservations unless script detects otherwise.
// No reservations indicated by -1
currentReservation = -1;
// loop through the events array and if current time falls between start and end of a element in the array the mark it as a reservation currently in progress
for (var i in events) {
if (dtNow >= events[i].start && dtNow <= events[i].end) currentReservation = i;
}
// Print the result to a output div
if (-1 == currentReservation) {
reservationInfo = '<h1>ROOM AVAILABLE</h1>';
$('#output').html(reservationInfo);
} else {
reservationInfo = '<h1>ROOM OCCUPIED</h1>';
$('#output').html(reservationInfo);
}
});
</script>
</head>
<body>
<div id="output"></div>
</body>
</html>
Some observations...
1) Do some refactor to your code and always do some debugging!
2) Your events variable is not the expected object since ajax calls are asynchronous and other code gets executed before getting into the callback that will fill your object. In other words, you need to wait for ajax call otherwise your object won't be the expected one (maybe will be undefined at first and after a moment, when ajax call finishes, an object with data).
Just to know, you can force an ajax call to be synchronous but that's NOT a good approach.
Try this:
I like to work this way, code it's way better organized:
Live Demo: http://jsfiddle.net/oscarj24/8HVj7/
HTML:
<div id="output"></div>
jQuery:
/*
* http://stackoverflow.com/questions/23205399/conference-room-availability-in-javascript
* #author: Oscar Jara
*/
/* Google calendar URL */
var url = 'http://www.google.com/calendar/feeds/4occ2bc4m626a3pgmirlm06q5s%40group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&futureevents=true&singleevents=true&max-results=2&alt=json';
/* Status list used to show final message to UI */
var statusList = {
'ROOM_A': 'Available',
'ROOM_O': 'Occupied',
'ERROR_DATA': 'No data found at Google calendar.',
'ERROR_PROCESS': 'There was an error checking room availability.'
};
/* Document onReady handler */
$(document).ready(function () {
getCalData(url);
});
/*
* Get Google calendar data by request.
* #param {String} url
*/
function getCalData(url) {
var statusCode;
$.getJSON(url, function (data) {
if (!$.isEmptyObject(data)) {
var events = parseCalData(data);
var curReserv = getCurrentReservation(events);
statusCode = getRoomStatusCode(curReserv);
} else {
statusCode = 'ERROR_DATA';
}
printRoomStatusToUI(statusCode, $('#output'));
}).fail(function (r) { // HTTP communication error
console.error(r);
});
};
/*
* Parse Google calendar data.
* #param {Object} data
* #return {Object} events
*/
function parseCalData(data) {
var events;
events = $.map(data.feed.entry, function (evt, i) {
var dt = evt['gd$when'][0];
return {
start: new Date(dt.startTime),
end: new Date(dt.endTime),
title: evt.title.$t,
summary: evt.content.$t
};
});
if (events) {
sortEvents(events); // Just in case
}
return events;
};
/*
* Sort Google calendar events.
* #param {Object} events
*/
function sortEvents(events) {
events.sort(function (a, b) {
return a.start - b.start;
});
}
/*
* Get/check for current reservation.
* If current time falls between start and end of an event,
* mark it as a reservation currently in progress.
* #param {Object} events
* #return {int} curReserv
*/
function getCurrentReservation(events) {
var curReserv;
if (events) {
var dtNow = new Date(); // Current datetime
curReserv = -1; // No reservations
for (var i in events) {
var dtStart = events[i].start;
var dtEnd = events[i].end;
if (dtNow >= dtStart && dtNow <= dtEnd) {
curReserv = i;
break;
}
}
}
return curReserv;
};
/*
* Get room availability statusCode.
* #param {int} curReserv
* #return {String} statusCode
*/
function getRoomStatusCode(curReserv) {
var statusCode = 'ROOM_A';
if (!curReserv) {
statusCode = 'ERROR_PROCESS';
} else if (curReserv && curReserv != -1) {
statusCode = 'ROOM_O';
}
return statusCode;
};
/*
* #private
* Get room status text.
* #param {String} statusCode
* #return {String}
*/
function getRoomStatusText(statusCode) {
return statusList[statusCode];
};
/*
* #private
* Check if statusCode is an ERROR one.
* #param {String} statusCode
* #return {Boolean}
*/
function isErrorStatus(statusCode) {
return (statusCode.indexOf('ERROR') > -1);
};
/*
* Print room availability to UI.
* #param {String} statusCode
* #param {Object} elem
*/
function printRoomStatusToUI(statusCode, elem) {
var statusText = getRoomStatusText(statusCode);
var isError = isErrorStatus(statusCode);
if (statusText && $.trim(statusText) != '') {
if (!isError) {
statusText = '<h1>Room is: ' + statusText + '</h1>';
}
elem.html(statusText);
}
};
You can quickly check what state a variable is by using:
console.log(variableName);
This will output the results of the variable in your browser console tab (in Developer Tools).
In your case, I did console.log(events); where the events were to be looped, and I discovered that events were not being set. After some debugging, I determined that the code was $.getJSON() function wasn't completing 100% before the code below it was running (most likely because the ajax request takes time).
To fix this, I've moved all of your code that parses the events within the $.getJSON() function so that the events are properly retrieved and set before parsing the data.
Your code will look like this now:
Working JSFiddle: http://jsfiddle.net/Mf8vb/4/
// Declare global variables
// Parse Google Calendar Public JSON Feed and store in the events global array
$(document).ready(function () {
var events = [];
var currentReservation = null;
var nextReservation = null;
var gclaData = 'http://www.google.com/calendar/feeds/4occ2bc4m626a3pgmirlm06q5s%40group.calendar.google.com/public/full?orderby=starttime&sortorder=ascending&futureevents=true&singleevents=true&max-results=2&alt=json';
$.getJSON(gclaData, function (data) {
$.each(data.feed.entry, function (i, entry) {
var dtStart = new Date(entry["gd$when"][0].startTime);
var dtEnd = new Date(entry["gd$when"][0].endTime);
var dtSummary = entry.content.$t;
var dtTitle = entry.title.$t;
events[i] = {
'start': dtStart,
'end': dtEnd,
'title': dtTitle,
'summary': dtSummary
};
});
reservationInfo = '';
// sort events just in case (JSON should be sorted anyways)
events.sort(function (a, b) {
return a.start - b.start;
});
// current date
var dtNow = new Date();
// let's assume there are no current room reservations unless script detects otherwise.
// No reservations indicated by -1
currentReservation = -1;
// loop through the events array and if current time falls between start and end of a element in the array the mark it as a reservation currently in progress
for (var i in events) {
if (dtNow >= events[i].start && dtNow <= events[i].end)
currentReservation = i;
}
// Print the result to a output div
if (-1 == currentReservation) {
reservationInfo = '<h1>ROOM AVAILABLE</h1>';
$('#output').html(reservationInfo);
} else {
reservationInfo = '<h1>ROOM OCCUPIED</h1>';
$('#output').html(reservationInfo);
}
});
});