1 | // |
2 | // JSONRowFormatter.cpp |
3 | // |
4 | // Library: Data |
5 | // Package: DataCore |
6 | // Module: JSONRowFormatter |
7 | // |
8 | // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/Data/JSONRowFormatter.h" |
16 | #include "Poco/String.h" |
17 | #include "Poco/JSONString.h" |
18 | #include "Poco/Format.h" |
19 | |
20 | |
21 | using Poco::trimInPlace; |
22 | using Poco::format; |
23 | using Poco::toJSON; |
24 | |
25 | |
26 | namespace Poco { |
27 | namespace Data { |
28 | |
29 | |
30 | const int JSONRowFormatter::JSON_FMT_MODE_SMALL; |
31 | const int JSONRowFormatter::JSON_FMT_MODE_ROW_COUNT; |
32 | const int JSONRowFormatter::JSON_FMT_MODE_COLUMN_NAMES; |
33 | const int JSONRowFormatter::JSON_FMT_MODE_FULL; |
34 | |
35 | |
36 | JSONRowFormatter::JSONRowFormatter(int mode) : RowFormatter("{" , "]}" ), |
37 | _firstTime(true) |
38 | { |
39 | if (mode == JSON_FMT_MODE_FULL) |
40 | { |
41 | mode |= JSON_FMT_MODE_ROW_COUNT; |
42 | mode |= JSON_FMT_MODE_COLUMN_NAMES; |
43 | //setPostfix("]}"); |
44 | } |
45 | |
46 | setJSONMode(mode); |
47 | } |
48 | |
49 | |
50 | JSONRowFormatter::~JSONRowFormatter() |
51 | { |
52 | } |
53 | |
54 | |
55 | void JSONRowFormatter::adjustPrefix() |
56 | { |
57 | if (printRowCount()) |
58 | { |
59 | std::ostringstream ostr; |
60 | ostr << "{\"count\":" << getTotalRowCount() << "," ; |
61 | if (_mode & JSON_FMT_MODE_FULL) |
62 | ostr << '['; |
63 | setPrefix(ostr.str()); |
64 | } |
65 | } |
66 | |
67 | |
68 | void JSONRowFormatter::setJSONMode(int mode) |
69 | { |
70 | if (mode < JSON_FMT_MODE_SMALL || |
71 | mode > (JSON_FMT_MODE_SMALL | JSON_FMT_MODE_ROW_COUNT | JSON_FMT_MODE_COLUMN_NAMES | JSON_FMT_MODE_FULL)) |
72 | { |
73 | throw Poco::InvalidArgumentException( |
74 | Poco::format("JSONRowFormatter mode must be between " |
75 | "%d (JSON_FMT_MODE_SMALL) and %d (JSON_FMT_MODE_FULL)" , |
76 | JSON_FMT_MODE_SMALL, |
77 | JSON_FMT_MODE_FULL)); |
78 | } |
79 | |
80 | _mode = mode; |
81 | if (!(_mode & JSON_FMT_MODE_SMALL) && !(_mode & JSON_FMT_MODE_FULL)) |
82 | _mode |= JSON_FMT_MODE_SMALL; |
83 | else if (_mode & JSON_FMT_MODE_FULL) |
84 | { |
85 | _mode |= JSON_FMT_MODE_ROW_COUNT; |
86 | } |
87 | |
88 | adjustPrefix(); |
89 | } |
90 | |
91 | |
92 | std::string& JSONRowFormatter::formatValues(const ValueVec& vals, std::string& formattedValues) |
93 | { |
94 | std::ostringstream str; |
95 | if (!_firstTime) str << ','; |
96 | if (isSmall()) |
97 | { |
98 | if (_firstTime) |
99 | { |
100 | if (printColumnNames()) |
101 | str << ",\"values\":" ; |
102 | |
103 | str << '['; |
104 | } |
105 | |
106 | str << '['; |
107 | ValueVec::const_iterator it = vals.begin(); |
108 | ValueVec::const_iterator end = vals.end(); |
109 | for (; it != end;) |
110 | { |
111 | if (!it->isEmpty()) |
112 | { |
113 | if (it->isString() || it->isDate() || it->isTime()) |
114 | { |
115 | std::string val = it->convert<std::string>(); |
116 | trimInPlace(val); |
117 | str << toJSON(val); |
118 | } |
119 | else |
120 | str << it->convert<std::string>(); |
121 | } |
122 | else |
123 | str << "null" ; |
124 | |
125 | if (++it == end) break; |
126 | |
127 | str << ','; |
128 | } |
129 | str << ']'; |
130 | } |
131 | else if (isFull()) |
132 | { |
133 | str << '{'; |
134 | ValueVec::const_iterator it = vals.begin(); |
135 | ValueVec::const_iterator end = vals.end(); |
136 | NameVec::iterator nIt = _pNames->begin(); |
137 | NameVec::iterator nEnd = _pNames->end(); |
138 | for (; it != end && nIt != nEnd; ++nIt) |
139 | { |
140 | if (!it->isEmpty()) |
141 | { |
142 | if (it->isString() || it->isDate() || it->isTime()) |
143 | { |
144 | std::string val = it->convert<std::string>(); |
145 | trimInPlace(val); |
146 | str << '"' << *nIt << "\":" << toJSON(val); |
147 | } |
148 | else |
149 | str << '"' << *nIt << "\":" << it->convert<std::string>(); |
150 | } |
151 | else |
152 | str << '"' << *nIt << "\":null" ; |
153 | |
154 | if (++it != end) str << ','; |
155 | } |
156 | str << '}'; |
157 | } |
158 | |
159 | _firstTime = false; |
160 | return formattedValues = str.str(); |
161 | } |
162 | |
163 | |
164 | std::string& JSONRowFormatter::formatNames(const NameVecPtr pNames, std::string& formattedNames) |
165 | { |
166 | if (isFull()) |
167 | { |
168 | // names are used in formatValues |
169 | if (pNames && !_pNames) _pNames = pNames; |
170 | return formattedNames = "" ; |
171 | } |
172 | else if (printColumnNames()) |
173 | { |
174 | std::ostringstream ostr; |
175 | ostr << "\"names\":[" ; |
176 | for (NameVec::const_iterator it = pNames->begin(), |
177 | end = pNames->end();;) |
178 | { |
179 | ostr << '"' << *it << '"'; |
180 | if (++it == end) break; |
181 | ostr << ','; |
182 | } |
183 | ostr << "]" ; |
184 | return formattedNames = ostr.str(); |
185 | } |
186 | |
187 | return formattedNames = "" ; |
188 | } |
189 | |
190 | |
191 | } }// namespace Poco::Data |
192 | |