#include "json/json.h"
#include <google/protobuf/descriptor.h>
#include <google/protobuf/message.h>
#include "pro1.pb.h"
#include "pro2.pb.h"
#include <fstream>
#include <iostream>
#include <cstdio>
using namespace ::google::protobuf;
using namespace std;
using namespace Json;
using namespace pro1;
using namespace pro2;
typedef long long ll;
string outputname[10]={"ans1.json","ans2.json"};
//对protobuf 反射机制的应用是实现程序的关键
typedef ::google::protobuf::Message ProtobufMsg; //消息类型
typedef ::google::protobuf::Reflection ProtobufReflection; //反射
typedef ::google::protobuf::FieldDescriptor ProtobufFieldDescriptor;//字段的描述
typedef ::google::protobuf::Descriptor ProtobufDescriptor; //对象的描述
void RepeatedMessage2Json(const ProtobufMsg& message, const ProtobufFieldDescriptor* field,const ProtobufReflection* reflection, Json::Value& json, bool enum2str) ;
//pb对象 js对象 是否转换enum
void PbMsg2Json(const ProtobufMsg& src, Json::Value& dst, bool enum2str =false)
{
// 拿到对象的描述包. --形式
const ProtobufDescriptor* descriptor = src.GetDescriptor();
//获取失败的报错
if (descriptor == NULL )
{
cout <<"描述包获取失败"<<endl;
return;
}
// 拿到对象的反射配置. --实际值
//对pb对象的自动读写主要通过该类完成
const ProtobufReflection* reflection = src.GetReflection();
if(reflection == NULL)
{
cout <<"反射配置获取失败"<<endl;
return;
}
//得到当前对象的数据字段个数
int count = descriptor->field_count();
//以下针对每个字段进行相应的操作
for (int i = 0; i < count; ++i)
{
//拿到对象第i个字段的描述
const ProtobufFieldDescriptor* field = descriptor->field(i);
if(field==NULL)
{
cout<<"对象第i个字段的描述获取失败"<<endl;
return ;
}
//若当前字段是数组 确实有重复的值
if (field->is_repeated())
{
if (reflection->FieldSize(src, field) > 0)//若当前字段实际存在赋值进入处理repeated操作
RepeatedMessage2Json(src, field, reflection, dst[field->name()], enum2str);//field->name()
continue;
}
//若当前字段虽然是数组 但实际上没有被赋值
if (!reflection->HasField(src, field))
{
continue;
}
//对不同的字段类型
switch (field->type())
{
//嵌套一个message
case ProtobufFieldDescriptor::TYPE_MESSAGE:
{
const ProtobufMsg& tmp_message = reflection->GetMessage(src, field);
if ( tmp_message.ByteSize()) PbMsg2Json(tmp_message, dst[field->name()],enum2str);//操作field->name()字段
break;
}
//bool
case ProtobufFieldDescriptor::TYPE_BOOL:
dst[field->name()] = reflection->GetBool(src, field) ? true : false;
break;
//ENUM
case ProtobufFieldDescriptor::TYPE_ENUM:
{
const ::google::protobuf::EnumValueDescriptor* enum_value_desc = reflection->GetEnum(src, field);
if (enum2str) //是否需要将enum数据转换成相应字符串
{
dst[field->name()] = enum_value_desc->name();
}
else
{
dst[field->name()] = enum_value_desc->number();
}
break;
}
case ProtobufFieldDescriptor::TYPE_INT32:
case ProtobufFieldDescriptor::TYPE_SINT32:
case ProtobufFieldDescriptor::TYPE_SFIXED32:
dst[field->name()] = Json::Int(reflection->GetInt32(src, field));
break;
case ProtobufFieldDescriptor::TYPE_UINT32:
case ProtobufFieldDescriptor::TYPE_FIXED32:
dst[field->name()] = Json::UInt(reflection->GetUInt32(src, field));
break;
case ProtobufFieldDescriptor::TYPE_INT64:
case ProtobufFieldDescriptor::TYPE_SINT64:
case ProtobufFieldDescriptor::TYPE_SFIXED64:
dst[field->name()] = Json::Int64(reflection->GetInt64(src, field));
break;
case ProtobufFieldDescriptor::TYPE_UINT64:
case ProtobufFieldDescriptor::TYPE_FIXED64:
dst[field->name()] = Json::UInt64(reflection->GetUInt64(src, field));
break;
case ProtobufFieldDescriptor::TYPE_FLOAT:
dst[field->name()] = reflection->GetFloat(src, field);
break;
case ProtobufFieldDescriptor::TYPE_DOUBLE:
dst[field->name()] = reflection->GetDouble(src, field);
break;
case ProtobufFieldDescriptor::TYPE_STRING:
case ProtobufFieldDescriptor::TYPE_BYTES:
dst[field->name()] = reflection->GetString(src, field);
break;
default:
break;
}
}
}
//pb 字段 反射实值 json对象
void RepeatedMessage2Json(const ProtobufMsg& message,const ProtobufFieldDescriptor* field,const ProtobufReflection* reflection, Json::Value& json, bool enum2str)
{
if (NULL == field )
{
cout<<"字段传入失败"<<endl;
return ;
//PbMsg2Json(message, json, enum2str);
}
//对字段中的重复数据进行判断
for (int i = 0; i < reflection->FieldSize(message, field); ++i)
{
Json::Value tmp_json;
switch (field->type())
{
//若重复mes
case ProtobufFieldDescriptor::TYPE_MESSAGE:
{
//获得mes数组字段中第i个mes
const ProtobufMsg& tmp_message = reflection->GetRepeatedMessage(message, field, i);
//只要该mes存在字节则进行转换
if ( tmp_message.ByteSize())
{
PbMsg2Json(tmp_message, tmp_json , enum2str);
}
break;
}
case ProtobufFieldDescriptor::TYPE_BOOL:
tmp_json[field->name()] = reflection->GetRepeatedBool(message, field, i) ? true : false;
break;
case ProtobufFieldDescriptor::TYPE_ENUM:
{
const ::google::protobuf::EnumValueDescriptor* enum_value_desc = reflection->GetRepeatedEnum(message, field, i);
if (enum2str)
{
tmp_json = enum_value_desc->name();
}
else
{
tmp_json = enum_value_desc->number();
}
break;
}
case ProtobufFieldDescriptor::TYPE_INT32:
case ProtobufFieldDescriptor::TYPE_SINT32:
case ProtobufFieldDescriptor::TYPE_SFIXED32:
tmp_json[field->name()] = reflection->GetRepeatedInt32(message, field, i);
break;
case ProtobufFieldDescriptor::TYPE_UINT32:
case ProtobufFieldDescriptor::TYPE_FIXED32:
tmp_json[field->name()] = reflection->GetRepeatedUInt32(message, field, i);
break;
case ProtobufFieldDescriptor::TYPE_INT64:
case ProtobufFieldDescriptor::TYPE_SINT64:
case ProtobufFieldDescriptor::TYPE_SFIXED64:
tmp_json[field->name()] = (Json::Int64)reflection->GetRepeatedInt64(message, field, i);
break;
case ProtobufFieldDescriptor::TYPE_UINT64:
case ProtobufFieldDescriptor::TYPE_FIXED64:
tmp_json[field->name()] = Json::UInt64(reflection->GetRepeatedUInt64(message, field, i));
break;
case ProtobufFieldDescriptor::TYPE_FLOAT:
tmp_json[field->name()] = reflection->GetRepeatedFloat(message, field, i);
break;
case ProtobufFieldDescriptor::TYPE_STRING:
case ProtobufFieldDescriptor::TYPE_BYTES:
tmp_json[field->name()] = reflection->GetRepeatedString(message, field, i);
break;
default:
break;
}
//对这个数组进行
json.append(tmp_json);
}
}
void init1(pro1:: Person &person)
{
cout<<"<//设置protobuf1初始值中...\n"<<endl;
person.set_name("Zed222");
person.set_id(222);
person.set_email("1208086@qq.com");
pro1::Person::PhoneNumber *phone1 = person.add_phones();// add_phones 返回指针类型
phone1->set_number("17569150186");
phone1->set_type(pro1::Person::MOBILE);
pro1::Person::PhoneNumber *phone2 = person.add_phones();
phone2->set_number("110");
phone2->set_type(pro1::Person::HOME);
}
void init2(pro2:: City &city)
{
cout<<"<//设置protobuf2初始值中...\n"<<endl;
city.set_nowname("Beijing");
city.set_id(110000);
city.set_gdp(41610.9);
city.set_country("Chinese");
city.add_usedname("Peking");
city.add_usedname("燕京");
city.add_usedname("幽州");
}
void output(Json::Value &root,int num)
{
if(num==1)
{
ofstream ofs(outputname[num-1]);
if(!ofs.is_open())
{
printf("打开%s失败\n",&outputname[num-1]);
exit(1);
}
ofs<<root<<endl;
ofs.close();
}
else if(num==2)
{
ofstream ofs(outputname[num-1]);
if(!ofs.is_open())
{
printf("打开%s失败\n",&outputname[num-1]);
exit(1);
}
ofs<<root<<endl;
ofs.close();
}
printf("输出到%d完毕\n",num);
}
void work(int num)
{
Json::Value root;
pro1::Person person;
pro2::City city;
if(num==1)
{
init1(person);
PbMsg2Json(person,root,true);
}
else
{
init2(city);
PbMsg2Json(city,root,true);
}
printf("数据%d转换中...\n",num);
output(root,num);
}
int main()
{
work(1);
work(2);
return 0;
}
将任意的protobuf对象转换为json格式的字符串
最新推荐文章于 2024-03-14 11:39:11 发布