我正在用 Go 开发 gRPC 用户服务,并面临着解组 JSON 的问题,其中在搜索条件中包含
google.protobuf.BoolValue
类型字段。
这是我的
proto
文件:
syntax = "proto3";
package user;
import "google/protobuf/wrappers.proto";
option go_package = "/pb;user";
message User {
int32 id = 1;
string fname = 2;
string city = 3;
int64 phone = 4;
float height = 5;
bool married = 6;
}
message UserID {
int32 id = 1;
}
message UserIDs {
repeated int32 ids = 1;
}
message SearchCriteria {
string city = 1;
int64 phone = 2;
google.protobuf.BoolValue married = 3;
}
message Users {
repeated User users = 1;
}
service UserService {
rpc GetUser(UserID) returns (User);
rpc GetUsers(UserIDs) returns (Users);
rpc SearchUsers(SearchCriteria) returns (Users);
}
这是我的服务器 Go 代码的相关部分:
package main
import (
"context"
"database/sql"
"fmt"
"log"
"net"
pb "golang-grcp-user-services/pb"
_ "github.com/mattn/go-sqlite3"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
"google.golang.org/protobuf/types/known/wrapperspb"
)
type server struct {
pb.UnimplementedUserServiceServer
db *sql.DB
}
func (s *server) SearchUsers(ctx context.Context, in *pb.SearchCriteria) (*pb.Users, error) {
var users []*pb.User
query := "SELECT id, fname, city, phone, height, married FROM users WHERE 1=1"
var args []interface{}
if in.City != "" {
query += " AND city LIKE ?"
args = append(args, "%"+in.City+"%")
}
if in.Phone != 0 {
phoneStr := fmt.Sprintf("%d", in.Phone)
query += " AND CAST(phone AS TEXT) LIKE ?"
args = append(args, "%"+phoneStr+"%")
}
if in.Married != nil {
query += " AND married = ?"
args = append(args, in.Married.Value)
}
rows, err := s.db.Query(query, args...)
if err != nil {
return nil, fmt.Errorf("failed to execute query: %v", err)
}
defer rows.Close()
for rows.Next() {
var user pb.User
err := rows.Scan(&user.Id, &user.Fname, &user.City, &user.Phone, &user.Height, &user.Married)
if err != nil {
return nil, fmt.Errorf("failed to scan row: %v", err)
}
users = append(users, &user)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error iterating rows: %v", err)
}
return &pb.Users{Users: users}, nil
}
当我用
grpcurl
测试时:
grpcurl -plaintext -d '{"phone": 9998887776, "married": {"value": false}}' localhost:50051 user.UserService/SearchUsers
我收到以下错误:
Error invoking method "user.UserService/SearchUsers": error getting request data: json: cannot unmarshal object into Go value of type bool
我尝试了各种方法来解决这个问题,但到目前为止还没有奏效。任何帮助或建议将不胜感激!
@notx 是正确的。
向自己证明这一点的方法是执行相反的操作并从
SearchCriteria
生成 JSON:
package main
import (
"log/slog"
"os"
pb "golang-grcp-user-services/pb"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/wrapperspb"
)
func main() {
sc := &pb.SearchCriteria{
Phone: 9998887776,
Married: &wrapperspb.BoolValue{
Value: false,
},
}
b, err := protojson.Marshal(sc)
if err != nil {
slog.Error("unable to marshal", "err", err)
os.Exit(1)
}
slog.Info("JSON", "b", string(b))
}
其产量:
{
"phone":"9998887776",
"married":false
}