You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Google Speech REST API与Go SDK的响应结构存在差异?

问题描述

通过REST方式调用Speech-To-Text API时,返回的响应结构与使用Golang SDK调用时存在细微差异。
示例场景:通过Golang SDK提交异步语音识别任务后,分别通过REST、Go SDK两种方式向Google Cloud查询该转录任务结果,得到的返回结果存在格式差异。

方法1:REST调用

请求格式:

GET https://speech.googleapis.com/v1/operations/{id}

{id}为操作ID,示例值:2593790426826555555

返回结果特征:属性为驼峰命名格式,其中startTime、endTime属性为string类型。
示例片段:

"words": [
  {
    "startTime": "0s",
    "endTime": "0.400s",
    "word": "We",
    "confidence": 0.98762906
  },
...

方法2:Go SDK调用

调用代码片段(省略错误处理):

client, err := speech.NewClient(ctx)
op, err := client.LROClient.GetOperation(ctx, &lropb.GetOperationRequest{Name: id})
resp := new(speechpb.LongRunningRecognizeResponse)
err = op.GetResponse().UnmarshalTo(resp)
js, err := json.Marshal(resp)
ioutil.WriteFile("sdk-response.json", js, 0644)

返回结果特征:start_time/end_time为蛇形命名的对象类型。
示例片段:

"words": [
{
  "start_time": {},
  "end_time": {
    "nanos": 400000000
  },
  "word": "We",
  "confidence": 0.98762906
},
...

查阅SDK代码中的类型定义,结构体确实使用start_time作为JSON标签:

StartTime *durationpb.Duration `protobuf:"bytes,1,opt,name=start_time,json=startTime,proto3" json:"start_time,omitempty"`

本次使用的环境版本为Go 1.18.1、cloud.google.com/go/speech v1.4.0。

问题补充

现有两套通过不同方式获取的转录文本:

  • 一套从Google Cloud Storage存储桶拉取,Google在存储桶中持久化的内容为驼峰命名格式(与REST API格式一致)
  • 另一套通过SDK API拉取,使用Golang的JSON编码持久化,会按照SDK的结构体定义采用蛇形命名格式

虽然手动写代码做格式归一难度不高,但该现象存在明显不一致性,需要确认该差异是操作错误导致可通过代码修正,还是服务的预期正常行为。


回答

这个差异是预期内的正常行为,你的反序列化操作没有问题,问题出在序列化JSON的环节用了不匹配的序列化器。

核心原因如下:

  • REST接口返回、GCS存储桶中持久化的JSON,是Google服务端按照官方API JSON规范序列化的结果:字段统一用驼峰命名,google.protobuf.Duration类型会序列化为带s后缀的标准时间字符串格式。
  • 你在代码里直接调用Go标准库json.Marshal序列化Protobuf生成的响应结构体时,标准库只会识别结构体上写死的json:"xxx"标签——也就是你看到的蛇形命名规则,同时会把*durationpb.Duration这类嵌套结构体序列化成带seconds、nanos字段的普通对象,自然和服务端返回的格式对不上。

你贴的结构体标签其实已经给出了线索:Protobuf标签里标注的json=startTime是给Protobuf专属JSON序列化器识别的,标准库encoding/json不会读取这个配置。

如果要让SDK序列化出来的结果和REST接口、GCS存储的格式完全一致,不需要自己写字段转换逻辑,替换序列化器即可:

  1. 引入Protobuf官方的JSON序列化包:google.golang.org/protobuf/encoding/protojson
  2. 把代码里的js, err := json.Marshal(resp)替换为js, err := protojson.Marshal(resp)

用protojson序列化输出的JSON会自动遵循Google API的JSON规范:字段为驼峰命名,Duration类型输出为标准时间字符串,和REST返回结果完全对齐。
你当前使用的SDK版本、op.GetResponse().UnmarshalTo(resp)反序列化逻辑均没有错误。


内容的提问来源于stack exchange,提问作者lifebythedrop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 22:21:30