Search code examples
gogrpcgo-gorm

When trying to get a structure with string and uint32 types through a gRPC request, it is all shifted into one key


I'm trying to get a structure from a database. I use gorm and gRPC for this. Previously, I used only string data types. and there were no problems. Here is my struct that was previously for gorm:

type Book struct {
    BookID  string `gorm:"primarykey;autoIncrement"`
    Name    string
    Year    string
    Edition string
    Authors []*Author `gorm:"many2many:book_author"`
}

former struct generated by file.proto:

type Book struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    Bookid  string `protobuf:"bytes,1,opt,name=bookid,proto3" json:"bookid,omitempty"`
    Name    string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
    Year    string `protobuf:"bytes,3,opt,name=year,proto3" json:"year,omitempty"`
    Edition string `protobuf:"bytes,4,opt,name=edition,proto3" json:"edition,omitempty"`
}

and a function on the server side that handles all this:

func (*server) UpdateBook(ctx context.Context, req *pb.UpdateBookRequest) (*pb.UpdateBookResponse, error) {
    fmt.Println("Update Book")
    var book Book
    reqBook := req.GetBook()

    res := DB.Model(&book).Where("book_id=?", reqBook.Bookid).Updates(
        Book{Name: reqBook.Name, Year: reqBook.Year, Edition: reqBook.Edition})

    if res.RowsAffected == 0 {
        return nil, errors.New("Books not found")
    }

    return &pb.UpdateBookResponse{
        Book: &pb.Book{
            Bookid:  book.BookID,
            Name:    book.Name,
            Year:    book.Year,
            Edition: book.Edition,
        },
    }, nil
}

as a result, when sending a gRPC request to getBooks(), I got what I needed:

{
    "books": [
        {
            "bookid": "",
            "name": "Логические ошибки",
            "year": "2017",
            "edition": "1"
        },
        {
            "bookid": "",
            "name": "LINUX API исчерпывающее руководство",
            "year": "2017",
            "edition": "1"
        },
        {
            "bookid": "",
            "name": "Сказки громовых",
            "year": "1999",
            "edition": "1"
        },
        {
            "bookid": "",
            "name": "Алгоритмы. Руководство по разработке",
            "year": "2022",
            "edition": "3"
        },

Then, for gorm to work correctly, I needed to change the bookid data type from string to uint32, file.proto was also regenerated. Current gorm struct:

type Book struct {
    BookID  uint32 `gorm:"primarykey;autoIncrement"`
    Name    string
    Year    string
    Edition string
    Authors []*Author `gorm:"many2many:book_author"`
}

Current struct generated by file.proto:

type Book struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    Bookid  uint32 `protobuf:"varint,1,opt,name=bookid,proto3" json:"bookid,omitempty"`
    Name    string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
    Year    string `protobuf:"bytes,3,opt,name=year,proto3" json:"year,omitempty"`
    Edition string `protobuf:"bytes,4,opt,name=edition,proto3" json:"edition,omitempty"`
}

But now when sending a gRPC request, I get all the values in one line of the key:

{
    "books": [
        {
            "bookid": "",
            "name": "",
            "year": "",
            "edition": "еские ошибки2017\"1\nH\b;LINUX API исчерпывающее руководство2017\"1\n*\bСказки громовых1999\"1\nQ\bDАлгоритмы. Руководство по разработке2022\"3\n\"\bРоман Светы2003\"1"
        }
    ]
}

The reason for this behavior of the function is not clear to me, and if you send everything in json format, then the result comes correct (client-side code is written for json)

I tried to bring everything back, but because of this, gorm did not work properly

I would like to get the same desired result as before, but at the same time do not change data types, because correct operation depends on them gorm, but it seems my knowledge is not enough

I also tried to configure the encoding of gorm for correct operation

dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
        dbUser,
        password,
        host,
        port,
        dbName,
    )

DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
DB.AutoMigrate(Book{})


Solution

  • I'm sorry, I'm a fool who forgot to change file.proto to a new file.proto in the insomnia, therefore, the unexpected behavior of the function occurred enter image description here