4 #include "util/pb2json.h" 6 #include <google/protobuf/reflection.h> 7 #include <google/protobuf/repeated_field.h> 8 #include <rapidjson/error/en.h> 9 #include <rapidjson/reader.h> 10 #include <rapidjson/writer.h> 12 #include "absl/container/inlined_vector.h" 13 #include "absl/strings/str_cat.h" 14 #include "absl/strings/str_format.h" 15 #include "absl/types/optional.h" 16 #include "absl/types/variant.h" 18 #include "base/logging.h" 19 #include "util/pb/refl.h" 22 namespace gpb = ::google::protobuf;
23 namespace rj = ::rapidjson;
28 typedef gpb::FieldDescriptor FD;
30 rj::Writer<rj::StringBuffer, rj::UTF8<>, rj::UTF8<>, rj::CrtAllocator, rj::kWriteNanAndInfFlag>;
32 void PrintValue(
const gpb::Message& msg,
const Pb2JsonOptions& options,
33 const gpb::FieldDescriptor* fd,
const gpb::Reflection* refl, RapidWriter* res);
34 void PrintRepeated(
const gpb::Message& msg,
const Pb2JsonOptions& options,
35 const gpb::FieldDescriptor* fd,
const gpb::Reflection* refl, RapidWriter* res);
37 void Pb2JsonInternal(const ::google::protobuf::Message& msg,
const Pb2JsonOptions& options,
39 const gpb::Descriptor* descr = msg.GetDescriptor();
40 const gpb::Reflection* refl = msg.GetReflection();
42 for (
int i = 0; i < descr->field_count(); ++i) {
43 const gpb::FieldDescriptor* fd = descr->field(i);
44 bool is_set = (fd->is_repeated() && refl->FieldSize(msg, fd) > 0) || fd->is_required() ||
45 (fd->is_optional() && refl->HasField(msg, fd));
49 const string& fname = options.field_name_cb ? options.field_name_cb(*fd) : fd->name();
52 res->Key(fname.c_str(), fname.size());
53 if (fd->is_repeated()) {
54 PrintRepeated(msg, options, fd, refl, res);
56 PrintValue(msg, options, fd, refl, res);
62 void PrintValue(
const gpb::Message& msg,
const Pb2JsonOptions& options,
63 const gpb::FieldDescriptor* fd,
const gpb::Reflection* refl, RapidWriter* res) {
64 switch (fd->cpp_type()) {
65 case FD::CPPTYPE_INT32:
66 res->Int(refl->GetInt32(msg, fd));
68 case FD::CPPTYPE_UINT32:
69 res->Uint(refl->GetUInt32(msg, fd));
71 case FD::CPPTYPE_INT64:
72 res->Int64(refl->GetInt64(msg, fd));
74 case FD::CPPTYPE_UINT64:
75 res->Uint64(refl->GetUInt64(msg, fd));
77 case FD::CPPTYPE_FLOAT: {
78 float fval = refl->GetFloat(msg, fd);
80 int sz = absl::SNPrintF(buf,
sizeof(buf),
"%.7g", fval);
81 res->RawValue(buf, sz, rj::kNumberType);
83 case FD::CPPTYPE_DOUBLE:
84 res->Double(refl->GetDouble(msg, fd));
86 case FD::CPPTYPE_STRING: {
88 const string& value = refl->GetStringReference(msg, fd, &scratch);
89 res->String(value.c_str(), value.size());
91 case FD::CPPTYPE_BOOL: {
92 bool b = refl->GetBool(msg, fd);
94 if (options.bool_as_int && options.bool_as_int(*fd)) {
101 case FD::CPPTYPE_ENUM:
102 if (options.enum_as_ints) {
103 res->Int(refl->GetEnum(msg, fd)->number());
105 const auto& tmp = refl->GetEnum(msg, fd)->name();
106 res->String(tmp.c_str(), tmp.size());
109 case FD::CPPTYPE_MESSAGE:
110 Pb2JsonInternal(refl->GetMessage(msg, fd), options, res);
113 LOG(FATAL) <<
"Not supported field " << fd->cpp_type_name();
117 template <FD::CppType t,
typename Cb>
118 void UnwindArr(
const gpb::Message& msg,
const gpb::FieldDescriptor* fd,
const gpb::Reflection* refl,
120 using CppType =
typename pb::FD_Traits_t<t>;
121 const auto& arr = refl->GetRepeatedFieldRef<CppType>(msg, fd);
122 std::for_each(std::begin(arr), std::end(arr), cb);
125 void PrintRepeated(
const gpb::Message& msg,
const Pb2JsonOptions& options,
126 const gpb::FieldDescriptor* fd,
const gpb::Reflection* refl, RapidWriter* res) {
128 switch (fd->cpp_type()) {
129 case FD::CPPTYPE_INT32:
130 UnwindArr<FD::CPPTYPE_INT32>(msg, fd, refl, [res](
auto val) { res->Int(val); });
132 case FD::CPPTYPE_UINT32:
133 UnwindArr<FD::CPPTYPE_UINT32>(msg, fd, refl, [res](
auto val) { res->Uint(val); });
135 case FD::CPPTYPE_INT64:
136 UnwindArr<FD::CPPTYPE_INT64>(msg, fd, refl, [res](
auto val) { res->Int64(val); });
138 case FD::CPPTYPE_UINT64:
139 UnwindArr<FD::CPPTYPE_UINT64>(msg, fd, refl, [res](
auto val) { res->Uint64(val); });
141 case FD::CPPTYPE_FLOAT:
142 UnwindArr<FD::CPPTYPE_FLOAT>(msg, fd, refl, [res](
auto val) { res->Double(val); });
144 case FD::CPPTYPE_DOUBLE:
145 UnwindArr<FD::CPPTYPE_DOUBLE>(msg, fd, refl, [res](
auto val) { res->Double(val); });
147 case FD::CPPTYPE_STRING:
148 UnwindArr<FD::CPPTYPE_STRING>(
149 msg, fd, refl, [res](
const string& val) { res->String(val.c_str(), val.size()); });
151 case FD::CPPTYPE_BOOL:
152 UnwindArr<FD::CPPTYPE_BOOL>(msg, fd, refl, [res](
auto val) { res->Bool(val); });
155 case FD::CPPTYPE_ENUM: {
156 int sz = refl->FieldSize(msg, fd);
157 for (
int i = 0; i < sz; ++i) {
158 const gpb::EnumValueDescriptor* edescr = refl->GetRepeatedEnum(msg, fd, i);
159 const string& name = edescr->name();
160 res->String(name.c_str(), name.size());
163 case FD::CPPTYPE_MESSAGE: {
164 const auto& arr = refl->GetRepeatedFieldRef<gpb::Message>(msg, fd);
165 std::unique_ptr<gpb::Message> scratch_space(arr.NewMessage());
166 for (
int i = 0; i < arr.size(); ++i) {
167 Pb2JsonInternal(arr.Get(i, scratch_space.get()), options, res);
171 LOG(FATAL) <<
"Not supported field " << fd->cpp_type_name();
177 const Json2PbOptions& opts_;
183 PbHandler(
const Json2PbOptions& opts, ::google::protobuf::Message* msg) : opts_(opts) {
184 stack_.emplace_back(msg->GetReflection(), msg);
187 bool Key(
const Ch* str,
size_t len,
bool copy);
189 bool String(
const Ch* str,
size_t len,
bool);
193 bool EndObject(
size_t member_count);
198 bool Uint(
unsigned i);
199 bool Int64(int64_t i);
200 bool Uint64(uint64_t i);
201 bool Double(
double d);
204 bool RawNumber(
const Ch* str,
size_t length,
bool copy) {
return false; }
207 bool EndArray(
size_t elementCount);
210 bool IntRepeated(
int i);
211 bool UintRepeated(
unsigned i);
212 bool Int64Repeated(int64_t i);
213 bool UInt64Repeated(uint64_t i);
214 bool DoubleRepeated(
double d);
216 using FD = gpb::FieldDescriptor;
217 template <
typename T>
using MRFR = gpb::MutableRepeatedFieldRef<T>;
220 absl::variant<MRFR<bool>, MRFR<uint32_t>, MRFR<int32_t>, MRFR<uint64_t>, MRFR<int64_t>,
221 MRFR<float>, MRFR<double>, MRFR<string>, MRFR<gpb::Message>>;
224 const gpb::Reflection* refl;
227 absl::optional<std::pair<const FD*, ArrRef>> arr_ref;
229 Object(
const gpb::Reflection* r, gpb::Message* m) : refl(r), msg(m) {}
231 template <FD::CppType t>
auto& GetArray() {
232 return absl::get<MRFR<pb::FD_Traits_t<t>>>(arr_ref->second);
236 template <FD::CppType t>
static auto MakeArr(
const FD* f,
const Object& o) {
237 return std::pair<const FD*, ArrRef>{f, pb::GetMutableArray<t>(o.refl, f, o.msg)};
240 absl::InlinedVector<Object, 16> stack_;
241 const gpb::FieldDescriptor* field_ =
nullptr;
244 unsigned disabled_level_ = 0;
247 bool PbHandler::Key(
const Ch* str,
size_t len,
bool copy) {
248 if (disabled_level_ > 1) {
252 key_name_.assign(str, len);
254 DCHECK(!stack_.empty());
255 auto& obj = stack_.back();
257 const auto& msg = *obj.msg;
258 field_ = msg.GetDescriptor()->FindFieldByName(key_name_);
260 return field_ !=
nullptr || opts_.skip_unknown_fields;
263 bool PbHandler::String(
const Ch* str,
size_t len,
bool) {
264 DCHECK(!stack_.empty());
265 auto& obj = stack_.back();
267 const string str_val(str, len);
270 obj.GetArray<FD::CPPTYPE_STRING>().Add(str_val);
275 return opts_.skip_unknown_fields;
277 switch (field_->cpp_type()) {
278 case FD::CPPTYPE_STRING:
279 obj.refl->SetString(obj.msg, field_, str_val);
281 case FD::CPPTYPE_ENUM: {
282 const gpb::EnumValueDescriptor* ev = field_->enum_type()->FindValueByName(str_val);
285 obj.refl->SetEnum(obj.msg, field_, ev);
296 bool PbHandler::StartObject() {
297 DCHECK(!stack_.empty());
299 auto& obj = stack_.back();
301 const FD* field = obj.arr_ref->first;
302 if (field->cpp_type() != FD::CPPTYPE_MESSAGE) {
303 err_msg = absl::StrCat(
"Expected msg type but found ", field->cpp_type_name());
306 gpb::Message* child = obj.refl->AddMessage(obj.msg, field);
307 stack_.emplace_back(child->GetReflection(), child);
313 return disabled_level_ == 1 || opts_.skip_unknown_fields;
316 if (field_->cpp_type() != gpb::FieldDescriptor::CPPTYPE_MESSAGE) {
317 err_msg = absl::StrCat(
"Error in StartObject, type ", field_->cpp_type_name());
321 gpb::Message* child = obj.refl->MutableMessage(obj.msg, field_);
322 stack_.emplace_back(child->GetReflection(), child);
326 bool PbHandler::EndObject(
size_t member_count) {
327 if (disabled_level_ > 1) {
329 DCHECK(field_ ==
nullptr);
333 DVLOG(2) <<
"EndObject " << member_count;
339 bool PbHandler::Null() {
340 auto& obj = stack_.back();
341 if (field_ && !obj.arr_ref) {
342 obj.refl->ClearField(obj.msg, field_);
349 SetField<FD::Type>(obj.refl, field_, i, obj.msg); \ 352 bool PbHandler::Bool(
bool b) {
353 auto& obj = stack_.back();
355 const FD* field = obj.arr_ref->first;
356 if (field->cpp_type() != FD::CPPTYPE_BOOL) {
357 err_msg = absl::StrCat(
"Expected msg type but found ", field->cpp_type_name());
360 obj.GetArray<FD::CPPTYPE_BOOL>().Add(b);
365 return opts_.skip_unknown_fields;
367 if (field_->cpp_type() != FD::CPPTYPE_BOOL) {
368 err_msg = absl::StrCat(
"Expected BOOL, found ", field_->cpp_type_name());
372 pb::SetField<FD::CPPTYPE_BOOL>(obj.refl, field_, b, obj.msg);
377 bool PbHandler::Int(
int i) {
378 auto& obj = stack_.back();
381 return IntRepeated(i);
385 return !key_name_.empty() && opts_.skip_unknown_fields;
389 switch (field_->cpp_type()) {
393 CASE(CPPTYPE_DOUBLE);
395 err_msg = absl::StrCat(
"Unexpected int type ", field_->cpp_type_name());
401 bool PbHandler::IntRepeated(
int i) {
402 auto& obj = stack_.back();
404 const FD* field = obj.arr_ref->first;
405 switch (field->cpp_type()) {
406 case FD::CPPTYPE_INT32:
407 obj.GetArray<FD::CPPTYPE_INT32>().Add(i);
409 case FD::CPPTYPE_INT64:
410 obj.GetArray<FD::CPPTYPE_INT64>().Add(i);
412 case FD::CPPTYPE_FLOAT:
413 obj.GetArray<FD::CPPTYPE_FLOAT>().Add(i);
415 case FD::CPPTYPE_DOUBLE:
416 obj.GetArray<FD::CPPTYPE_DOUBLE>().Add(i);
419 err_msg = absl::StrCat(
"Unexpected int type ", field_->cpp_type_name());
426 bool PbHandler::Uint(
unsigned i) {
427 auto& obj = stack_.back();
429 return UintRepeated(i);
433 return !key_name_.empty() && opts_.skip_unknown_fields;
437 switch (field_->cpp_type()) {
439 CASE(CPPTYPE_UINT32);
441 CASE(CPPTYPE_UINT64);
443 CASE(CPPTYPE_DOUBLE);
444 case FD::CPPTYPE_BOOL:
446 err_msg = absl::StrCat(
"Invalid bool value ", i);
449 SetField<FD::CPPTYPE_BOOL>(obj.refl, field_, i != 0, obj.msg);
452 err_msg = absl::StrCat(
"Unexpected Uint type ", field_->cpp_type_name());
460 bool PbHandler::Int64(int64_t i) {
461 auto& obj = stack_.back();
463 return Int64Repeated(i);
467 return !key_name_.empty() && opts_.skip_unknown_fields;
472 switch (field_->cpp_type()) {
475 CASE(CPPTYPE_DOUBLE);
484 bool PbHandler::Uint64(uint64_t i) {
485 auto& obj = stack_.back();
487 return UInt64Repeated(i);
491 return !key_name_.empty() && opts_.skip_unknown_fields;
495 switch (field_->cpp_type()) {
496 CASE(CPPTYPE_UINT64);
498 CASE(CPPTYPE_DOUBLE);
500 err_msg = absl::StrCat(
"Unexpected Uint64 type ", field_->cpp_type_name());
508 bool PbHandler::Double(
double i) {
509 auto& obj = stack_.back();
511 return DoubleRepeated(i);
515 return !key_name_.empty() && opts_.skip_unknown_fields;
520 switch (field_->cpp_type()) {
522 CASE(CPPTYPE_DOUBLE);
524 err_msg = absl::StrCat(
"Unexpected Double type ", field_->cpp_type_name());
534 bool PbHandler::UintRepeated(
unsigned i) {
535 auto& obj = stack_.back();
537 const FD* field = obj.arr_ref->first;
539 switch (field->cpp_type()) {
540 case FD::CPPTYPE_INT32:
541 obj.GetArray<FD::CPPTYPE_INT32>().Add(i);
543 case FD::CPPTYPE_UINT32:
544 obj.GetArray<FD::CPPTYPE_UINT32>().Add(i);
546 case FD::CPPTYPE_INT64:
547 obj.GetArray<FD::CPPTYPE_INT64>().Add(i);
549 case FD::CPPTYPE_UINT64:
550 obj.GetArray<FD::CPPTYPE_UINT64>().Add(i);
552 case FD::CPPTYPE_FLOAT:
553 obj.GetArray<FD::CPPTYPE_FLOAT>().Add(i);
555 case FD::CPPTYPE_DOUBLE:
556 obj.GetArray<FD::CPPTYPE_DOUBLE>().Add(i);
558 case FD::CPPTYPE_BOOL:
560 err_msg = absl::StrCat(
"Invalid bool value ", i);
563 obj.GetArray<FD::CPPTYPE_BOOL>().Add(i != 0);
566 err_msg = absl::StrCat(
"Unexpected uint type ", field_->cpp_type_name());
573 bool PbHandler::Int64Repeated(int64_t i) {
574 auto& obj = stack_.back();
576 const FD* field = obj.arr_ref->first;
578 switch (field->cpp_type()) {
579 case FD::CPPTYPE_INT64:
580 obj.GetArray<FD::CPPTYPE_INT64>().Add(i);
582 case FD::CPPTYPE_FLOAT:
583 obj.GetArray<FD::CPPTYPE_FLOAT>().Add(i);
585 case FD::CPPTYPE_DOUBLE:
586 obj.GetArray<FD::CPPTYPE_DOUBLE>().Add(i);
589 err_msg = absl::StrCat(
"Unexpected uint type ", field_->cpp_type_name());
596 bool PbHandler::UInt64Repeated(uint64_t i) {
597 auto& obj = stack_.back();
599 const FD* field = obj.arr_ref->first;
601 switch (field->cpp_type()) {
602 case FD::CPPTYPE_UINT64:
603 obj.GetArray<FD::CPPTYPE_UINT64>().Add(i);
605 case FD::CPPTYPE_FLOAT:
606 obj.GetArray<FD::CPPTYPE_FLOAT>().Add(i);
608 case FD::CPPTYPE_DOUBLE:
609 obj.GetArray<FD::CPPTYPE_DOUBLE>().Add(i);
612 err_msg = absl::StrCat(
"Unexpected uint type ", field_->cpp_type_name());
619 bool PbHandler::DoubleRepeated(
double d) {
620 auto& obj = stack_.back();
622 const FD* field = obj.arr_ref->first;
624 switch (field->cpp_type()) {
625 case FD::CPPTYPE_FLOAT:
626 obj.GetArray<FD::CPPTYPE_FLOAT>().Add(d);
628 case FD::CPPTYPE_DOUBLE:
629 obj.GetArray<FD::CPPTYPE_DOUBLE>().Add(d);
632 err_msg = absl::StrCat(
"Unexpected double type ", field_->cpp_type_name());
639 bool PbHandler::StartArray() {
642 return opts_.skip_unknown_fields;
645 if (!field_->is_repeated()) {
646 err_msg = absl::StrCat(
"Bad array ", key_name_);
649 using FD = gpb::FieldDescriptor;
650 auto& obj = stack_.back();
651 DCHECK(!obj.arr_ref);
655 obj.arr_ref.emplace(MakeArr<FD::Type>(field_, obj)); \ 658 switch (field_->cpp_type()) {
659 CASE(CPPTYPE_UINT32);
661 CASE(CPPTYPE_UINT64);
663 CASE(CPPTYPE_DOUBLE);
665 CASE(CPPTYPE_STRING);
666 CASE(CPPTYPE_MESSAGE);
669 err_msg = absl::StrCat(
"Unknown array type ", field_->cpp_type_name());
676 bool PbHandler::EndArray(
size_t elementCount) {
677 auto& obj = stack_.back();
679 if (disabled_level_ > 1) {
680 DCHECK(!obj.arr_ref && field_ ==
nullptr);
693 std::string Pb2Json(const ::google::protobuf::Message& msg,
const Pb2JsonOptions& options) {
696 rw.SetMaxDecimalPlaces(9);
698 Pb2JsonInternal(msg, options, &rw);
699 return string(sb.GetString(), sb.GetSize());
702 Status Json2Pb(std::string json, ::google::protobuf::Message* msg,
const Json2PbOptions& opts) {
705 PbHandler h(opts, msg);
706 rj::InsituStringStream stream(&json.front());
708 rj::ParseResult pr = reader.Parse<rj::kParseInsituFlag | rj::kParseTrailingCommasFlag>(stream, h);
710 Status st(StatusCode::PARSE_ERROR,
711 absl::StrCat(rj::GetParseError_En(pr.Code()),
"/", h.err_msg));