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

如何将Protobuf转换为保留原始数据类型的JSON

问题:Protobuf转JSON时保留原始数据类型

我有如下Protobuf结构:

ad_group {
  resource_name: "customers/8776659915/adGroups/143689544046"
  status: ENABLED
  type: VIDEO_TRUE_VIEW_IN_STREAM
  id: 143689544046
  name: "Video Consideration - 2023-01-06"
  base_ad_group: "customers/8776659915/adGroups/143689544046"
  campaign: "customers/8776659915/campaigns/19500015051"
  cpc_bid_micros: 0
  cpm_bid_micros: 10000
  target_cpa_micros: 0
  cpv_bid_micros: 567000000
  target_cpm_micros: 10000
  effective_target_cpa_micros: 0
}

使用com.google.protobuf.util.JsonFormat转换为JSON的代码:

String jsonString = JsonFormat.printer().print(googleAdsRow);

转换后的JSON所有数值都被转为字符串类型:

{
  "adGroup": {
    "resourceName": "customers/8776659915/adGroups/143689544046",
    "status": "ENABLED",
    "type": "VIDEO_TRUE_VIEW_IN_STREAM",
    "id": "143689544046",
    "name": "Video Consideration - 2023-01-06",
    "baseAdGroup": "customers/8776659915/adGroups/143689544046",
    "campaign": "customers/8776659915/campaigns/19500015051",
    "cpcBidMicros": "0",
    "cpmBidMicros": "10000",
    "targetCpaMicros": "0",
    "cpvBidMicros": "567000000",
    "targetCpmMicros": "10000",
    "effectiveTargetCpaMicros": "0"
  }
}

想实现转换时保留原始数据类型,注意到JsonFormat.PrinterImpl的printSingleFieldValue方法有alwaysWithQuotes参数,但不知道如何调用,求解决办法。


解决方案

直接调用JsonFormat.printer()默认会给所有非字符串类型加引号,这是为了避免int64等数值类型转JSON时丢失精度,但可以通过配置JsonFormat.Printer的官方选项实现保留原始类型,无需调用内部的printSingleFieldValue方法。

方法1:使用官方提供的withoutQuotingNonStringFields()(推荐)

Protobuf 3.12及以上版本新增了withoutQuotingNonStringFields()方法,可让数值类型以原始JSON类型输出:

String jsonString = JsonFormat.printer()
    .withoutQuotingNonStringFields()
    .preservingProtoFieldNames() // 可选,若需要保留protobuf下划线命名格式
    .print(googleAdsRow);

转换后的JSON会保留数值的原始类型:

{
  "adGroup": {
    "resourceName": "customers/8776659915/adGroups/143689544046",
    "status": "ENABLED",
    "type": "VIDEO_TRUE_VIEW_IN_STREAM",
    "id": 143689544046,
    "name": "Video Consideration - 2023-01-06",
    "baseAdGroup": "customers/8776659915/adGroups/143689544046",
    "campaign": "customers/8776659915/campaigns/19500015051",
    "cpcBidMicros": 0,
    "cpmBidMicros": 10000,
    "targetCpaMicros": 0,
    "cpvBidMicros": 567000000,
    "targetCpmMicros": 10000,
    "effectiveTargetCpaMicros": 0
  }
}

方法2:适配旧版本Protobuf(3.12以下)

如果无法升级Protobuf版本,可通过继承PrinterImpl重写字段打印逻辑,但这种方式复杂度高且易出问题,优先推荐升级到支持withoutQuotingNonStringFields()的版本。

注意事项

  • int64类型转JSON数字后,在JavaScript等语言中可能因Number类型精度限制(仅能精确表示到2^53)出现精度丢失,若业务需跨语言处理超大数值,建议保留字符串类型,由消费端自行转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 08:44:58