如何将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
相关产品推荐
相关产品推荐

