Go语言 json联合国马歇尔没有在戈兰原型上工作

oipij1gg  于 2023-02-06  发布在  Go
关注(0)|答案(1)|浏览(138)

我收到此HTTP请求响应

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZCRXFDSnFER21hMUxLZUtoZUVxcSJ9.eyJpc3MiOiJodHRwczovL2Rldi0xY3p5M3Vpa21pNjJ0dWN4LnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0OTAiLCJhdWQiOiJhdXRoLXNlcnZpY2Ui...",
  "scope": "read:sample",
  "expires_in": 86400,
  "token_type": "Bearer"
}

我想将这个响应解组成下面的golang原型:

message Token {
  // jwt access token
  string access_token = 1;
  // scope of the token
  string scope = 2;
  // expiration time
  int32 expires_in = 3;
  // token type
  string token_type = 4;
}

下面是生成的go结构体:

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

    // jwt access token
    AccessToken string `protobuf:"bytes,1,opt,name=access_token,json=accessToken,proto3" json:"access_token,omitempty"`
    // scope of the token
    Scope string `protobuf:"bytes,2,opt,name=scope,proto3" json:"scope,omitempty"`
    // expiration time
    ExpiresIn int32 `protobuf:"varint,3,opt,name=expires_in,json=expiresIn,proto3" json:"expires_in,omitempty"`
    // token type
    TokenType string `protobuf:"bytes,4,opt,name=token_type,json=tokenType,proto3" json:"token_type,omitempty"`
}

我尝试了json/encoding包中的json.NewDecoder(resp.Body).Decode(&token)。还尝试了以下操作:

token := new(v1_stubs.Token)
    if err := jsonpb.Unmarshal(resp.Body, token); err != nil {
        log.Context(ctx).Errorf("failed to decode `get token` response")
        return nil, err
    }

在生成v1_stubs.Token的地方,执行上述原型的结构。

**问题是:**当我将token转换为json时,我得到的是输出:

{
    "token": {
        "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZCRXFDSnFER21hMUxLZUtoZUVxcSJ9.eyJpc3MiOiJodHRwczovL2Rldi0xY3p5M3Vpa21pNjJ0dWN4LnV...",
        "scope": "read:sample",
        "expires_in": "\"\u0006Bearer",
        "token_type": ""
    }
}

看起来expires_in字段中缺少一些数据,token_type合并到expires_in中。

wh6knrhe

wh6knrhe1#

这是一个从头开始的例子。也许你可以复制它,看看你的本地设置与这个有什么不同?jsonpb包的官方文档说,它是赞成"google.golang.org/protobuf/encoding/protojson"的弃用,所以我包括了两个代码样本,这两个看起来都像预期的工作。

// ex.proto
syntax = "proto3";

message Token {
  // jwt access token
  string access_token = 1;
  // scope of the token
  string scope = 2;
  // expiration time
  int32 expires_in = 3;
  // token type
  string token_type = 4;
}

我从https://github.com/protocolbuffers/protobuf/releases/tag/v21.12下载了这些工具的全新安装

$ unzip protoc-21.12-linux-x86_64.zip
$ PATH=$(pwd)/bin:$PATH
$ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
$ protoc -I=./ --go_out=./ --go_opt=Mex.proto=this/ex ex.proto
$ cd this
$ go mod init this

在此this目录中,创建main_jsonpb.go文件:

package main

import (
    "fmt"
    "log"

    "this/ex"

    "github.com/golang/protobuf/jsonpb"
)

func main() {
    d := `{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZCRXFDSnFER21hMUxLZUtoZUVxcSJ9.eyJpc3MiOiJodHRwczovL2Rldi0xY3p5M3Vpa21pNjJ0dWN4LnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0OTAiLCJhdWQiOiJhdXRoLXNlcnZpY2Ui...",
  "scope": "read:sample",
  "expires_in": 86400,
  "token_type": "Bearer"
}`
    var pr ex.Token
    if err := jsonpb.UnmarshalString(d, &pr); err != nil {
        log.Fatalf("failed to unmarshal json: %v", err)
    }
    f := &jsonpb.Marshaler{
        Indent: "  ",
    }
    fmt.Println(f.MarshalToString(&pr))
}

main_protojson.go文件:

package main

import (
    "fmt"
    "log"

    "this/ex"

    "google.golang.org/protobuf/encoding/protojson"
)

func main() {
    d := []byte(`{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZCRXFDSnFER21hMUxLZUtoZUVxcSJ9.eyJpc3MiOiJodHRwczovL2Rldi0xY3p5M3Vpa21pNjJ0dWN4LnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0OTAiLCJhdWQiOiJhdXRoLXNlcnZpY2Ui...",
  "scope": "read:sample",
  "expires_in": 86400,
  "token_type": "Bearer"
}`)
    var pr ex.Token
    if err := protojson.Unmarshal(d, &pr); err != nil {
        log.Fatalf("failed to unmarshal json: %v", err)
    }
    fmt.Println(protojson.Format(&pr))
}

然后执行它们:

$ go mod tidy
$ go run main_jsonpb.go
{
  "accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZCRXFDSnFER21hMUxLZUtoZUVxcSJ9.eyJpc3MiOiJodHRwczovL2Rldi0xY3p5M3Vpa21pNjJ0dWN4LnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0OTAiLCJhdWQiOiJhdXRoLXNlcnZpY2Ui...",
  "scope": "read:sample",
  "expiresIn": 86400,
  "tokenType": "Bearer"
} <nil>
$ go run main_protojson.go
{
  "accessToken": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImZCRXFDSnFER21hMUxLZUtoZUVxcSJ9.eyJpc3MiOiJodHRwczovL2Rldi0xY3p5M3Vpa21pNjJ0dWN4LnVzLmF1dGgwLmNvbS8iLCJzdWIiOiJhdXRoMHw0OTAiLCJhdWQiOiJhdXRoLXNlcnZpY2Ui...",
  "scope": "read:sample",
  "expiresIn": 86400,
  "tokenType": "Bearer"
}

相关问题