1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <jsonpb/jsonpb.h>
18 
19 #include <android-base/logging.h>
20 #include <google/protobuf/descriptor.h>
21 #include <google/protobuf/message.h>
22 #include <google/protobuf/util/json_util.h>
23 #include <google/protobuf/util/type_resolver_util.h>
24 
25 namespace android {
26 namespace jsonpb {
27 
28 using google::protobuf::DescriptorPool;
29 using google::protobuf::Message;
30 using google::protobuf::util::NewTypeResolverForDescriptorPool;
31 using google::protobuf::util::TypeResolver;
32 
33 static constexpr char kTypeUrlPrefix[] = "type.googleapis.com";
34 
GetTypeUrl(const Message & message)35 std::string GetTypeUrl(const Message& message) {
36     return std::string(kTypeUrlPrefix) + "/" + message.GetDescriptor()->full_name();
37 }
38 
MessageToJsonString(const Message & message)39 ErrorOr<std::string> MessageToJsonString(const Message& message) {
40     std::unique_ptr<TypeResolver> resolver(
41             NewTypeResolverForDescriptorPool(kTypeUrlPrefix, DescriptorPool::generated_pool()));
42 
43     google::protobuf::util::JsonOptions options;
44     options.add_whitespace = true;
45 
46     std::string json;
47     auto status = BinaryToJsonString(resolver.get(), GetTypeUrl(message),
48                                      message.SerializeAsString(), &json, options);
49 
50     if (!status.ok()) {
51         return MakeError<std::string>(status.error_message().as_string());
52     }
53     return ErrorOr<std::string>(std::move(json));
54 }
55 
56 namespace internal {
JsonStringToMessage(const std::string & content,Message * message)57 ErrorOr<std::monostate> JsonStringToMessage(const std::string& content, Message* message) {
58     std::unique_ptr<TypeResolver> resolver(
59             NewTypeResolverForDescriptorPool(kTypeUrlPrefix, DescriptorPool::generated_pool()));
60 
61     std::string binary;
62     auto status = JsonToBinaryString(resolver.get(), GetTypeUrl(*message), content, &binary);
63     if (!status.ok()) {
64         return MakeError<std::monostate>(status.error_message().as_string());
65     }
66     if (!message->ParseFromString(binary)) {
67         return MakeError<std::monostate>("Fail to parse.");
68     }
69     return ErrorOr<std::monostate>();
70 }
71 }  // namespace internal
72 
73 }  // namespace jsonpb
74 }  // namespace android
75