1*890232f2SAndroid Build Coastguard Worker /*
2*890232f2SAndroid Build Coastguard Worker * Copyright 2014 Google Inc. All rights reserved.
3*890232f2SAndroid Build Coastguard Worker *
4*890232f2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*890232f2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*890232f2SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*890232f2SAndroid Build Coastguard Worker *
8*890232f2SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*890232f2SAndroid Build Coastguard Worker *
10*890232f2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*890232f2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*890232f2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*890232f2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*890232f2SAndroid Build Coastguard Worker * limitations under the License.
15*890232f2SAndroid Build Coastguard Worker */
16*890232f2SAndroid Build Coastguard Worker
17*890232f2SAndroid Build Coastguard Worker #include <iostream>
18*890232f2SAndroid Build Coastguard Worker
19*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/code_generators.h"
20*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/idl.h"
21*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/util.h"
22*890232f2SAndroid Build Coastguard Worker
23*890232f2SAndroid Build Coastguard Worker namespace flatbuffers {
24*890232f2SAndroid Build Coastguard Worker
25*890232f2SAndroid Build Coastguard Worker namespace jsons {
26*890232f2SAndroid Build Coastguard Worker
27*890232f2SAndroid Build Coastguard Worker namespace {
28*890232f2SAndroid Build Coastguard Worker
29*890232f2SAndroid Build Coastguard Worker template<class T>
GenFullName(const T * enum_def)30*890232f2SAndroid Build Coastguard Worker static std::string GenFullName(const T *enum_def) {
31*890232f2SAndroid Build Coastguard Worker std::string full_name;
32*890232f2SAndroid Build Coastguard Worker const auto &name_spaces = enum_def->defined_namespace->components;
33*890232f2SAndroid Build Coastguard Worker for (auto ns = name_spaces.cbegin(); ns != name_spaces.cend(); ++ns) {
34*890232f2SAndroid Build Coastguard Worker full_name.append(*ns + "_");
35*890232f2SAndroid Build Coastguard Worker }
36*890232f2SAndroid Build Coastguard Worker full_name.append(enum_def->name);
37*890232f2SAndroid Build Coastguard Worker return full_name;
38*890232f2SAndroid Build Coastguard Worker }
39*890232f2SAndroid Build Coastguard Worker
40*890232f2SAndroid Build Coastguard Worker template<class T>
GenTypeRef(const T * enum_def)41*890232f2SAndroid Build Coastguard Worker static std::string GenTypeRef(const T *enum_def) {
42*890232f2SAndroid Build Coastguard Worker return "\"$ref\" : \"#/definitions/" + GenFullName(enum_def) + "\"";
43*890232f2SAndroid Build Coastguard Worker }
44*890232f2SAndroid Build Coastguard Worker
GenType(const std::string & name)45*890232f2SAndroid Build Coastguard Worker static std::string GenType(const std::string &name) {
46*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"" + name + "\"";
47*890232f2SAndroid Build Coastguard Worker }
48*890232f2SAndroid Build Coastguard Worker
GenType(BaseType type)49*890232f2SAndroid Build Coastguard Worker static std::string GenType(BaseType type) {
50*890232f2SAndroid Build Coastguard Worker switch (type) {
51*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_BOOL: return "\"type\" : \"boolean\"";
52*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_CHAR:
53*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"integer\", \"minimum\" : " +
54*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<int8_t>::min()) +
55*890232f2SAndroid Build Coastguard Worker ", \"maximum\" : " +
56*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<int8_t>::max());
57*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_UCHAR:
58*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"integer\", \"minimum\" : 0, \"maximum\" :" +
59*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<uint8_t>::max());
60*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_SHORT:
61*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"integer\", \"minimum\" : " +
62*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<int16_t>::min()) +
63*890232f2SAndroid Build Coastguard Worker ", \"maximum\" : " +
64*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<int16_t>::max());
65*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_USHORT:
66*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"integer\", \"minimum\" : 0, \"maximum\" : " +
67*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<uint16_t>::max());
68*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_INT:
69*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"integer\", \"minimum\" : " +
70*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<int32_t>::min()) +
71*890232f2SAndroid Build Coastguard Worker ", \"maximum\" : " +
72*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<int32_t>::max());
73*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_UINT:
74*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"integer\", \"minimum\" : 0, \"maximum\" : " +
75*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<uint32_t>::max());
76*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_LONG:
77*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"integer\", \"minimum\" : " +
78*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<int64_t>::min()) +
79*890232f2SAndroid Build Coastguard Worker ", \"maximum\" : " +
80*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<int64_t>::max());
81*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_ULONG:
82*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"integer\", \"minimum\" : 0, \"maximum\" : " +
83*890232f2SAndroid Build Coastguard Worker NumToString(std::numeric_limits<uint64_t>::max());
84*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_FLOAT:
85*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_DOUBLE: return "\"type\" : \"number\"";
86*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_STRING: return "\"type\" : \"string\"";
87*890232f2SAndroid Build Coastguard Worker default: return "";
88*890232f2SAndroid Build Coastguard Worker }
89*890232f2SAndroid Build Coastguard Worker }
90*890232f2SAndroid Build Coastguard Worker
GenBaseType(const Type & type)91*890232f2SAndroid Build Coastguard Worker static std::string GenBaseType(const Type &type) {
92*890232f2SAndroid Build Coastguard Worker if (type.struct_def != nullptr) { return GenTypeRef(type.struct_def); }
93*890232f2SAndroid Build Coastguard Worker if (type.enum_def != nullptr) { return GenTypeRef(type.enum_def); }
94*890232f2SAndroid Build Coastguard Worker return GenType(type.base_type);
95*890232f2SAndroid Build Coastguard Worker }
96*890232f2SAndroid Build Coastguard Worker
GenArrayType(const Type & type)97*890232f2SAndroid Build Coastguard Worker static std::string GenArrayType(const Type &type) {
98*890232f2SAndroid Build Coastguard Worker std::string element_type;
99*890232f2SAndroid Build Coastguard Worker if (type.struct_def != nullptr) {
100*890232f2SAndroid Build Coastguard Worker element_type = GenTypeRef(type.struct_def);
101*890232f2SAndroid Build Coastguard Worker } else if (type.enum_def != nullptr) {
102*890232f2SAndroid Build Coastguard Worker element_type = GenTypeRef(type.enum_def);
103*890232f2SAndroid Build Coastguard Worker } else {
104*890232f2SAndroid Build Coastguard Worker element_type = GenType(type.element);
105*890232f2SAndroid Build Coastguard Worker }
106*890232f2SAndroid Build Coastguard Worker
107*890232f2SAndroid Build Coastguard Worker return "\"type\" : \"array\", \"items\" : {" + element_type + "}";
108*890232f2SAndroid Build Coastguard Worker }
109*890232f2SAndroid Build Coastguard Worker
GenType(const Type & type)110*890232f2SAndroid Build Coastguard Worker static std::string GenType(const Type &type) {
111*890232f2SAndroid Build Coastguard Worker switch (type.base_type) {
112*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_ARRAY: FLATBUFFERS_FALLTHROUGH(); // fall thru
113*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_VECTOR: {
114*890232f2SAndroid Build Coastguard Worker return GenArrayType(type);
115*890232f2SAndroid Build Coastguard Worker }
116*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_STRUCT: {
117*890232f2SAndroid Build Coastguard Worker return GenTypeRef(type.struct_def);
118*890232f2SAndroid Build Coastguard Worker }
119*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_UNION: {
120*890232f2SAndroid Build Coastguard Worker std::string union_type_string("\"anyOf\": [");
121*890232f2SAndroid Build Coastguard Worker const auto &union_types = type.enum_def->Vals();
122*890232f2SAndroid Build Coastguard Worker for (auto ut = union_types.cbegin(); ut < union_types.cend(); ++ut) {
123*890232f2SAndroid Build Coastguard Worker const auto &union_type = *ut;
124*890232f2SAndroid Build Coastguard Worker if (union_type->union_type.base_type == BASE_TYPE_NONE) { continue; }
125*890232f2SAndroid Build Coastguard Worker if (union_type->union_type.base_type == BASE_TYPE_STRUCT) {
126*890232f2SAndroid Build Coastguard Worker union_type_string.append(
127*890232f2SAndroid Build Coastguard Worker "{ " + GenTypeRef(union_type->union_type.struct_def) + " }");
128*890232f2SAndroid Build Coastguard Worker }
129*890232f2SAndroid Build Coastguard Worker if (union_type != *type.enum_def->Vals().rbegin()) {
130*890232f2SAndroid Build Coastguard Worker union_type_string.append(",");
131*890232f2SAndroid Build Coastguard Worker }
132*890232f2SAndroid Build Coastguard Worker }
133*890232f2SAndroid Build Coastguard Worker union_type_string.append("]");
134*890232f2SAndroid Build Coastguard Worker return union_type_string;
135*890232f2SAndroid Build Coastguard Worker }
136*890232f2SAndroid Build Coastguard Worker case BASE_TYPE_UTYPE: return GenTypeRef(type.enum_def);
137*890232f2SAndroid Build Coastguard Worker default: {
138*890232f2SAndroid Build Coastguard Worker return GenBaseType(type);
139*890232f2SAndroid Build Coastguard Worker }
140*890232f2SAndroid Build Coastguard Worker }
141*890232f2SAndroid Build Coastguard Worker }
142*890232f2SAndroid Build Coastguard Worker
143*890232f2SAndroid Build Coastguard Worker } // namespace
144*890232f2SAndroid Build Coastguard Worker
145*890232f2SAndroid Build Coastguard Worker class JsonSchemaGenerator : public BaseGenerator {
146*890232f2SAndroid Build Coastguard Worker private:
147*890232f2SAndroid Build Coastguard Worker std::string code_;
148*890232f2SAndroid Build Coastguard Worker
149*890232f2SAndroid Build Coastguard Worker public:
JsonSchemaGenerator(const Parser & parser,const std::string & path,const std::string & file_name)150*890232f2SAndroid Build Coastguard Worker JsonSchemaGenerator(const Parser &parser, const std::string &path,
151*890232f2SAndroid Build Coastguard Worker const std::string &file_name)
152*890232f2SAndroid Build Coastguard Worker : BaseGenerator(parser, path, file_name, "", "", "json") {}
153*890232f2SAndroid Build Coastguard Worker
JsonSchemaGenerator(const BaseGenerator & base_generator)154*890232f2SAndroid Build Coastguard Worker explicit JsonSchemaGenerator(const BaseGenerator &base_generator)
155*890232f2SAndroid Build Coastguard Worker : BaseGenerator(base_generator) {}
156*890232f2SAndroid Build Coastguard Worker
GeneratedFileName(const std::string & path,const std::string & file_name,const IDLOptions & options) const157*890232f2SAndroid Build Coastguard Worker std::string GeneratedFileName(const std::string &path,
158*890232f2SAndroid Build Coastguard Worker const std::string &file_name,
159*890232f2SAndroid Build Coastguard Worker const IDLOptions &options /* unused */) const {
160*890232f2SAndroid Build Coastguard Worker (void)options;
161*890232f2SAndroid Build Coastguard Worker return path + file_name + ".schema.json";
162*890232f2SAndroid Build Coastguard Worker }
163*890232f2SAndroid Build Coastguard Worker
164*890232f2SAndroid Build Coastguard Worker // If indentation is less than 0, that indicates we don't want any newlines
165*890232f2SAndroid Build Coastguard Worker // either.
NewLine() const166*890232f2SAndroid Build Coastguard Worker std::string NewLine() const {
167*890232f2SAndroid Build Coastguard Worker return parser_.opts.indent_step >= 0 ? "\n" : "";
168*890232f2SAndroid Build Coastguard Worker }
169*890232f2SAndroid Build Coastguard Worker
Indent(int indent) const170*890232f2SAndroid Build Coastguard Worker std::string Indent(int indent) const {
171*890232f2SAndroid Build Coastguard Worker const auto num_spaces = indent * std::max(parser_.opts.indent_step, 0);
172*890232f2SAndroid Build Coastguard Worker return std::string(num_spaces, ' ');
173*890232f2SAndroid Build Coastguard Worker }
174*890232f2SAndroid Build Coastguard Worker
PrepareDescription(const std::vector<std::string> & comment_lines)175*890232f2SAndroid Build Coastguard Worker std::string PrepareDescription(
176*890232f2SAndroid Build Coastguard Worker const std::vector<std::string> &comment_lines) {
177*890232f2SAndroid Build Coastguard Worker std::string comment;
178*890232f2SAndroid Build Coastguard Worker for (auto line_iterator = comment_lines.cbegin();
179*890232f2SAndroid Build Coastguard Worker line_iterator != comment_lines.cend(); ++line_iterator) {
180*890232f2SAndroid Build Coastguard Worker const auto &comment_line = *line_iterator;
181*890232f2SAndroid Build Coastguard Worker
182*890232f2SAndroid Build Coastguard Worker // remove leading and trailing spaces from comment line
183*890232f2SAndroid Build Coastguard Worker const auto start = std::find_if(comment_line.begin(), comment_line.end(),
184*890232f2SAndroid Build Coastguard Worker [](char c) { return !isspace(c); });
185*890232f2SAndroid Build Coastguard Worker const auto end =
186*890232f2SAndroid Build Coastguard Worker std::find_if(comment_line.rbegin(), comment_line.rend(), [](char c) {
187*890232f2SAndroid Build Coastguard Worker return !isspace(c);
188*890232f2SAndroid Build Coastguard Worker }).base();
189*890232f2SAndroid Build Coastguard Worker if (start < end) {
190*890232f2SAndroid Build Coastguard Worker comment.append(start, end);
191*890232f2SAndroid Build Coastguard Worker } else {
192*890232f2SAndroid Build Coastguard Worker comment.append(comment_line);
193*890232f2SAndroid Build Coastguard Worker }
194*890232f2SAndroid Build Coastguard Worker
195*890232f2SAndroid Build Coastguard Worker if (line_iterator + 1 != comment_lines.cend()) comment.append("\n");
196*890232f2SAndroid Build Coastguard Worker }
197*890232f2SAndroid Build Coastguard Worker if (!comment.empty()) {
198*890232f2SAndroid Build Coastguard Worker std::string description;
199*890232f2SAndroid Build Coastguard Worker if (EscapeString(comment.c_str(), comment.length(), &description, true,
200*890232f2SAndroid Build Coastguard Worker true)) {
201*890232f2SAndroid Build Coastguard Worker return description;
202*890232f2SAndroid Build Coastguard Worker }
203*890232f2SAndroid Build Coastguard Worker return "";
204*890232f2SAndroid Build Coastguard Worker }
205*890232f2SAndroid Build Coastguard Worker return "";
206*890232f2SAndroid Build Coastguard Worker }
207*890232f2SAndroid Build Coastguard Worker
generate()208*890232f2SAndroid Build Coastguard Worker bool generate() {
209*890232f2SAndroid Build Coastguard Worker code_ = "";
210*890232f2SAndroid Build Coastguard Worker if (parser_.root_struct_def_ == nullptr) {
211*890232f2SAndroid Build Coastguard Worker std::cerr << "Error: Binary schema not generated, no root struct found\n";
212*890232f2SAndroid Build Coastguard Worker return false;
213*890232f2SAndroid Build Coastguard Worker }
214*890232f2SAndroid Build Coastguard Worker code_ += "{" + NewLine();
215*890232f2SAndroid Build Coastguard Worker code_ += Indent(1) +
216*890232f2SAndroid Build Coastguard Worker "\"$schema\": \"https://json-schema.org/draft/2019-09/schema\"," +
217*890232f2SAndroid Build Coastguard Worker NewLine();
218*890232f2SAndroid Build Coastguard Worker code_ += Indent(1) + "\"definitions\": {" + NewLine();
219*890232f2SAndroid Build Coastguard Worker for (auto e = parser_.enums_.vec.cbegin(); e != parser_.enums_.vec.cend();
220*890232f2SAndroid Build Coastguard Worker ++e) {
221*890232f2SAndroid Build Coastguard Worker code_ += Indent(2) + "\"" + GenFullName(*e) + "\" : {" + NewLine();
222*890232f2SAndroid Build Coastguard Worker code_ += Indent(3) + GenType("string") + "," + NewLine();
223*890232f2SAndroid Build Coastguard Worker auto enumdef(Indent(3) + "\"enum\": [");
224*890232f2SAndroid Build Coastguard Worker for (auto enum_value = (*e)->Vals().begin();
225*890232f2SAndroid Build Coastguard Worker enum_value != (*e)->Vals().end(); ++enum_value) {
226*890232f2SAndroid Build Coastguard Worker enumdef.append("\"" + (*enum_value)->name + "\"");
227*890232f2SAndroid Build Coastguard Worker if (*enum_value != (*e)->Vals().back()) { enumdef.append(", "); }
228*890232f2SAndroid Build Coastguard Worker }
229*890232f2SAndroid Build Coastguard Worker enumdef.append("]");
230*890232f2SAndroid Build Coastguard Worker code_ += enumdef + NewLine();
231*890232f2SAndroid Build Coastguard Worker code_ += Indent(2) + "}," + NewLine(); // close type
232*890232f2SAndroid Build Coastguard Worker }
233*890232f2SAndroid Build Coastguard Worker for (auto s = parser_.structs_.vec.cbegin();
234*890232f2SAndroid Build Coastguard Worker s != parser_.structs_.vec.cend(); ++s) {
235*890232f2SAndroid Build Coastguard Worker const auto &structure = *s;
236*890232f2SAndroid Build Coastguard Worker code_ += Indent(2) + "\"" + GenFullName(structure) + "\" : {" + NewLine();
237*890232f2SAndroid Build Coastguard Worker code_ += Indent(3) + GenType("object") + "," + NewLine();
238*890232f2SAndroid Build Coastguard Worker const auto &comment_lines = structure->doc_comment;
239*890232f2SAndroid Build Coastguard Worker auto comment = PrepareDescription(comment_lines);
240*890232f2SAndroid Build Coastguard Worker if (comment != "") {
241*890232f2SAndroid Build Coastguard Worker code_ += Indent(3) + "\"description\" : " + comment + "," + NewLine();
242*890232f2SAndroid Build Coastguard Worker }
243*890232f2SAndroid Build Coastguard Worker
244*890232f2SAndroid Build Coastguard Worker code_ += Indent(3) + "\"properties\" : {" + NewLine();
245*890232f2SAndroid Build Coastguard Worker
246*890232f2SAndroid Build Coastguard Worker const auto &properties = structure->fields.vec;
247*890232f2SAndroid Build Coastguard Worker for (auto prop = properties.cbegin(); prop != properties.cend(); ++prop) {
248*890232f2SAndroid Build Coastguard Worker const auto &property = *prop;
249*890232f2SAndroid Build Coastguard Worker std::string arrayInfo = "";
250*890232f2SAndroid Build Coastguard Worker if (IsArray(property->value.type)) {
251*890232f2SAndroid Build Coastguard Worker arrayInfo = "," + NewLine() + Indent(8) + "\"minItems\": " +
252*890232f2SAndroid Build Coastguard Worker NumToString(property->value.type.fixed_length) + "," +
253*890232f2SAndroid Build Coastguard Worker NewLine() + Indent(8) + "\"maxItems\": " +
254*890232f2SAndroid Build Coastguard Worker NumToString(property->value.type.fixed_length);
255*890232f2SAndroid Build Coastguard Worker }
256*890232f2SAndroid Build Coastguard Worker std::string deprecated_info = "";
257*890232f2SAndroid Build Coastguard Worker if (property->deprecated) {
258*890232f2SAndroid Build Coastguard Worker deprecated_info =
259*890232f2SAndroid Build Coastguard Worker "," + NewLine() + Indent(8) + "\"deprecated\" : true";
260*890232f2SAndroid Build Coastguard Worker }
261*890232f2SAndroid Build Coastguard Worker std::string typeLine = Indent(4) + "\"" + property->name + "\"";
262*890232f2SAndroid Build Coastguard Worker typeLine += " : {" + NewLine() + Indent(8);
263*890232f2SAndroid Build Coastguard Worker typeLine += GenType(property->value.type);
264*890232f2SAndroid Build Coastguard Worker typeLine += arrayInfo;
265*890232f2SAndroid Build Coastguard Worker typeLine += deprecated_info;
266*890232f2SAndroid Build Coastguard Worker auto description = PrepareDescription(property->doc_comment);
267*890232f2SAndroid Build Coastguard Worker if (description != "") {
268*890232f2SAndroid Build Coastguard Worker typeLine +=
269*890232f2SAndroid Build Coastguard Worker "," + NewLine() + Indent(8) + "\"description\" : " + description;
270*890232f2SAndroid Build Coastguard Worker }
271*890232f2SAndroid Build Coastguard Worker
272*890232f2SAndroid Build Coastguard Worker typeLine += NewLine() + Indent(7) + "}";
273*890232f2SAndroid Build Coastguard Worker if (property != properties.back()) { typeLine.append(","); }
274*890232f2SAndroid Build Coastguard Worker code_ += typeLine + NewLine();
275*890232f2SAndroid Build Coastguard Worker }
276*890232f2SAndroid Build Coastguard Worker code_ += Indent(3) + "}," + NewLine(); // close properties
277*890232f2SAndroid Build Coastguard Worker
278*890232f2SAndroid Build Coastguard Worker std::vector<FieldDef *> requiredProperties;
279*890232f2SAndroid Build Coastguard Worker std::copy_if(properties.begin(), properties.end(),
280*890232f2SAndroid Build Coastguard Worker back_inserter(requiredProperties),
281*890232f2SAndroid Build Coastguard Worker [](FieldDef const *prop) { return prop->IsRequired(); });
282*890232f2SAndroid Build Coastguard Worker if (!requiredProperties.empty()) {
283*890232f2SAndroid Build Coastguard Worker auto required_string(Indent(3) + "\"required\" : [");
284*890232f2SAndroid Build Coastguard Worker for (auto req_prop = requiredProperties.cbegin();
285*890232f2SAndroid Build Coastguard Worker req_prop != requiredProperties.cend(); ++req_prop) {
286*890232f2SAndroid Build Coastguard Worker required_string.append("\"" + (*req_prop)->name + "\"");
287*890232f2SAndroid Build Coastguard Worker if (*req_prop != requiredProperties.back()) {
288*890232f2SAndroid Build Coastguard Worker required_string.append(", ");
289*890232f2SAndroid Build Coastguard Worker }
290*890232f2SAndroid Build Coastguard Worker }
291*890232f2SAndroid Build Coastguard Worker required_string.append("],");
292*890232f2SAndroid Build Coastguard Worker code_ += required_string + NewLine();
293*890232f2SAndroid Build Coastguard Worker }
294*890232f2SAndroid Build Coastguard Worker code_ += Indent(3) + "\"additionalProperties\" : false" + NewLine();
295*890232f2SAndroid Build Coastguard Worker auto closeType(Indent(2) + "}");
296*890232f2SAndroid Build Coastguard Worker if (*s != parser_.structs_.vec.back()) { closeType.append(","); }
297*890232f2SAndroid Build Coastguard Worker code_ += closeType + NewLine(); // close type
298*890232f2SAndroid Build Coastguard Worker }
299*890232f2SAndroid Build Coastguard Worker code_ += Indent(1) + "}," + NewLine(); // close definitions
300*890232f2SAndroid Build Coastguard Worker
301*890232f2SAndroid Build Coastguard Worker // mark root type
302*890232f2SAndroid Build Coastguard Worker code_ += Indent(1) + "\"$ref\" : \"#/definitions/" +
303*890232f2SAndroid Build Coastguard Worker GenFullName(parser_.root_struct_def_) + "\"" + NewLine();
304*890232f2SAndroid Build Coastguard Worker
305*890232f2SAndroid Build Coastguard Worker code_ += "}" + NewLine(); // close schema root
306*890232f2SAndroid Build Coastguard Worker return true;
307*890232f2SAndroid Build Coastguard Worker }
308*890232f2SAndroid Build Coastguard Worker
save() const309*890232f2SAndroid Build Coastguard Worker bool save() const {
310*890232f2SAndroid Build Coastguard Worker const auto file_path = GeneratedFileName(path_, file_name_, parser_.opts);
311*890232f2SAndroid Build Coastguard Worker return SaveFile(file_path.c_str(), code_, false);
312*890232f2SAndroid Build Coastguard Worker }
313*890232f2SAndroid Build Coastguard Worker
getJson()314*890232f2SAndroid Build Coastguard Worker const std::string getJson() { return code_; }
315*890232f2SAndroid Build Coastguard Worker };
316*890232f2SAndroid Build Coastguard Worker } // namespace jsons
317*890232f2SAndroid Build Coastguard Worker
GenerateJsonSchema(const Parser & parser,const std::string & path,const std::string & file_name)318*890232f2SAndroid Build Coastguard Worker bool GenerateJsonSchema(const Parser &parser, const std::string &path,
319*890232f2SAndroid Build Coastguard Worker const std::string &file_name) {
320*890232f2SAndroid Build Coastguard Worker jsons::JsonSchemaGenerator generator(parser, path, file_name);
321*890232f2SAndroid Build Coastguard Worker if (!generator.generate()) { return false; }
322*890232f2SAndroid Build Coastguard Worker return generator.save();
323*890232f2SAndroid Build Coastguard Worker }
324*890232f2SAndroid Build Coastguard Worker
GenerateJsonSchema(const Parser & parser,std::string * json)325*890232f2SAndroid Build Coastguard Worker bool GenerateJsonSchema(const Parser &parser, std::string *json) {
326*890232f2SAndroid Build Coastguard Worker jsons::JsonSchemaGenerator generator(parser, "", "");
327*890232f2SAndroid Build Coastguard Worker if (!generator.generate()) { return false; }
328*890232f2SAndroid Build Coastguard Worker *json = generator.getJson();
329*890232f2SAndroid Build Coastguard Worker return true;
330*890232f2SAndroid Build Coastguard Worker }
331*890232f2SAndroid Build Coastguard Worker } // namespace flatbuffers
332