我正在使用grpc protobuf消息定义,并在Go中实现它们。
我的最终目标是让我的rpc在用户上检索一些json并返回带有可选嵌套消息的Profile
Message,用于解组json的子集。
使用此rpc:
rpc GetUser (GetUserRequest) returns (Profile) {
option (google.api.http) = {
get: "/user/{id=*}"
};
}
假设如下:
{
"profile": {
"foo": {
"name": "tim"
"age": 22
},
"bar": {
"level": 5
}
}
}
我想返回一个Profile
消息,该消息仅包含“foo”、“bar”或两者,作为基于grpc请求的传入运行时scope
参数的嵌套消息(目前,scope
将是包含用于将json子设置为相应消息的消息名称的字符串列表,例如["Foo","Bar"]
)。
给定这些Message定义:
message Profile {
//both Foo & Bar are optional by default
Foo foo = 1 [json_name="foo"];
Bar bar = 2 [json_name="bar"];
}
message Foo {
string name = 1 [json_name="name"];
int32 age = 2 [json_name="age"];
}
message Bar {
string level = 1 [json_name="level"];
}
然后,如果范围是,我希望rpc返回:
Profile{
Foo: // Foo Message unmarshalled from json
}
或者如果"scope"
是["Foo","Bar"]
那么:
Profile{
Foo:
Bar:
}
问题似乎可以归结为“duck-typing”消息类型。
我几乎用protoreflect
import(
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/reflect/protoreflect"
)
var scope protoreflect.FullName = "Foo"
var types = new(protoregistry.Types)
var message, errs = types.FindMessageByName(scope)
var almost_foo = message.New()
// using `myJson` object without top level "profile" key to make testing more simple at the moment
var myJson = `{ "foo": { .. }, "bar", { ... } }`
err = json.Unmarshal([]byte(myJson), almost_foo)
但当我尝试使用几乎_foo
创建配置文件消息时:
var profile = &pb.Profile{almost_foo}
我得到错误:不能使用几乎_foo(protoreflect.Message类型)作为类型*package_名称。字段值中的Foo
使用
import(
"github.com/jhump/protoreflect/desc"
"github.com/jhump/protoreflect/dynamic"
)
我尝试再次动态创建消息:
var fd, errs = desc.LoadFileDescriptor("github.com/package/path/..")
var message_desc = fd.FindMessage("Foo")
var almost_foo = dynamic.NewMessage(message_desc)
出现了一个类似的错误:不能使用几乎_foo(type*dynamic.Message)作为type*package_名称。字段值中的Foo
两次尝试几乎都会创建一条消息,但类型系统仍然不允许实际使用这两种消息。
感谢您的帮助。
我设法解决了这个问题,首先将json缩减到我想要的大小,然后将其解组。
我创建了一条顶级消息,将Profile
作为一个字段:
message GetUserResponse {
Profile profile = 1;
}
并重新定义了反应:
rpc GetUser (GetUserRequest) returns (GetUserResponse)
要构建允许/限定范围的json,我使用:
"github.com/tidwall/gjson"
"github.com/tidwall/sjson"
我将作用域路径(以点分隔,例如[“profile.foo”]
)指定的json复制到一个最初为空的输出响应_json
字符串中,并只构建允许返回的json。
var response_json string
var scopes = []string{"profile.foo"}
for _, scope := range scopes {
// copy allowed json subset in raw form
value := gjson.Get(myJson, scope + "|@ugly")
// if scope didn't copy a value, skip
if value.String() == "" {
continue
} else {
// write value to output json using SetRaw since value can be an object
response_json, _ = sjson.SetRaw(response_json, scope, value.Raw)
}
}
响应如下所示:
{
"profile": {
"foo": {
"name": "tim"
"age": 22
}
}
}
然后解开玛莎:
response = &pb.VerifyUserResponse{}
err = json.Unmarshal([]byte(response_json), response)
“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。” 我们并不关心对象是什么类型,到底是不是鸭子,只关心行为。 比如在python中,有很多file-like的东西,比如StringIO,GzipFile,socket。它们有很多相同的方法,我们把它们当作文件使用。 又比如list.extend()方法中,我们并不关心它的参数是不是list,只要它是可迭代的,
问题内容: 我试图在GO中创建错误的子类型,现在,我面临多种类型的问题。以下代码显示了错误类型定义: 当我尝试运行以下代码时: 该函数打印以下内容: 我需要将的类型标识为,而不是。我怎样才能做到这一点?我的方法有什么问题吗? 问题答案: 您使用了该方法,但是没有将其添加到“定义”接口中,因此请执行以下操作: 而你想成为一个。对于成为一个,它必须实现所有的方法:和。因此,您必须同时添加这两种方法:
问题内容: 在Go中,如何在运行时根据对象的类型创建对象的实例?我想您还需要先获取对象的实际值吗? 我正在尝试执行惰性实例化以节省内存。 问题答案: 为了做到这一点,你需要。 您可以使用结构类型(而不是int)执行相同的操作。还是其他的,真的。只需确保了解map和slice类型时new和make之间的区别即可。
我目前正在构建一个python gRPC服务器,它将大量不同的proto消息序列化为json,以将它们存储到无sql数据库中。我希望简化此服务器的扩展,这样我们就可以添加新类型,而无需重写gRPC服务器和重新部署。理想情况下,我们希望定义一条新消息,将其放入一个proto文件中,并仅更新客户端。服务器首先应该期望任何类型,但知道。进行序列化/反序列化时要查找的原型文件或文件夹。 我读过关于“任何类
我试图用web3j编写一个Java应用程序,它可以读取任意的abi文件,向用户显示AbiDefinitions列表,并让用户调用自己选择的常量函数。我如何计算下面的输出类型? TypeReference 类对泛型类型使用技巧,当泛型类型在源代码中硬编码时,这些技巧可以正常工作,如下所示: 这就是生成的合约包装器要做的。 对于简单类型,我可以这样做: 对于“int256[2]”这样的数组类型,该怎么
问题内容: 我几乎没有这样声明的C函数 我想将这些作为一个Go函数公开 所以我需要能够在运行时检查 参数 类型。我该怎么做,这是个好主意吗(如果不是,在这种情况下,什么是好的做法)? 问题答案: 在此处查看类型断言: http://golang.org/ref/spec#Type_assertions 我只断言一个明智的类型(字符串,uint64)等,并使其尽可能宽松,最后执行到本机类型的转换。