Open honglei opened 2 years ago
JS(brower)<--JSON
--> Python(web server) <--GRPC
--> C++(file stransfer backend)
{
"sendFileDir": "/home/lccy/sendfile",
"publicMulitcastAddr": "223.0.1.1",
"linkID": 1,
"privateMulticastAddr": "234.0.1.1",
"CIR": 22333,
"channels": [
"\u7b2c\u4e00\u9891\u9053",
"\u7b2c\u4e8c\u9891\u9053"
],
"waitingFiles": [
"\u7b2c\u4e00\u9891\u9053/11.txt",
"\u7b2c\u4e8c\u9891\u9053/22.txt"
]
}
If you are serialising as JSON you can pass a betterproto.Casing to make sure that the field names are in camelCase
Question 1: betterproto.Casing.CAMEL
seems not enough:
message ReplyX{
bool aBigCDEndOne=1;//
}
import betterproto
from uftplink import ReplyX
a = ReplyX(a_big_cd_end_one=True)
b =a.to_dict(casing=betterproto.Casing.CAMEL )
expect = {'aBigCDEndOne':True}
assert b== expect #not equal
question 2: from JSON to ReplyX message?
question2.1: easy way from JSON to Nested-Type message?
message _FileInfo{
string name=1;
uint64 size=2;
}
message _SendFileStatus{
string name=1;
uint64 size=2;
uint64 sended =3;
}
message LinkFileStatus{
repeated _FileInfo waitingFiles=1;
_SendFileStatus currentFile=2;
}
a = {
"currentFile":{"name":"c/11.txt", "size":532323,"sended":3322,},
"waitingFiles":[
{"name":"c/12.txt",
"size":32325,
}
,{"name":"c/22.txt",
"size":32335,
}
],
}
LinkFileStatus( **a ) #not work
a changed generated Python file:
@dataclass(eq=False, repr=False)
class FileInfo(betterproto.Message):
name: str = betterproto.string_field(1)
size: int = betterproto.uint64_field(2)
@dataclass(eq=False, repr=False)
class SendFileStatus(betterproto.Message):
name: str = betterproto.string_field(1)
size: int = betterproto.uint64_field(2)
sended: int = betterproto.uint64_field(3)
@dataclass(eq=False, repr=False)
class LinkFileStatus(betterproto.Message):
waitingFiles: List[FileInfo] = betterproto.message_field(1)
currentFile: SendFileStatus = betterproto.message_field(2)
a simple JSON-> betterproto.Message
from betterproto import Message
def set_attrs(value_type:Message, value):
'''
oneof is not considered
'''
if value_type == Empty:
return Empty()
result = value_type()
for field_name, field_type in result.__annotations__.items():
if hasattr(field_type,'_name'):
list_field_type = field_type.__args__[0]
if field_type._name=='List': #repeated/python typing.List
if issubclass(list_field_type, Message):
list_value = [set_attrs(list_field_type, v) for v in value.get(field_name)]
setattr(result, field_name, list_value )
else:
setattr(result, field_name, value.get(field_name))
elif field_type._name =='Optional':
if issubclass(list_field_type, Message):
if field_value:= value.get(field_name):
setattr(result, field_name, set_attrs(list_field_type,field_value) )
elif issubclass(field_type, Message): #Nested Message
setattr(result, field_name, set_attrs(field_type, value.get(field_name)) )
else:
setattr(result, field_name, value.get(field_name))
return result
b = set_attrs(LinkFileStatus, a)
bytes(b)
Every prevailing project has its own name-style, forcing users to rename every name may be not a good idea. To communicate with Java/C++/JavaScript,
mixedCase
(also known asLower CamelCase
) is accepted by every other language, and it is much shorter than PEP8 suggested-style:private_multicast_addr
. In my case, the InitConfig is passed by an JSON-object from web client, changing the name back and forth is useless and boring.the generated python file by betterproto: