GDAL
cpl_json.h
Go to the documentation of this file.
1/******************************************************************************
2 * Project: Common Portability Library
3 * Purpose: Function wrapper for libjson-c access.
4 * Author: Dmitry Baryshnikov, dmitry.baryshnikov@nextgis.com
5 *
6 ******************************************************************************
7 * Copyright (c) 2017-2018 NextGIS, <info@nextgis.com>
8 *
9 * SPDX-License-Identifier: MIT
10 ****************************************************************************/
11
12#ifndef CPL_JSON_H_INCLUDED
13#define CPL_JSON_H_INCLUDED
14
15#include "cpl_progress.h"
16#include "cpl_string.h"
17
18#include <cstdint>
19#include <initializer_list>
20#include <iterator>
21#include <string>
22#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
23#include <string_view>
24#endif
25#include <vector>
26
34typedef void *JSONObjectH;
35
36class CPLJSONObject;
37class CPLJSONArray;
38
39class CPLJSONObjectProxy
40{
41 CPLJSONObject &oObj;
42 const std::string osName;
43
44 public:
45 explicit inline CPLJSONObjectProxy(CPLJSONObject &oObjIn,
46 const std::string &osNameIn)
47 : oObj(oObjIn), osName(osNameIn)
48 {
49 }
50
51 template <class T> inline CPLJSONObjectProxy &operator=(const T &val);
52};
53
59class CPL_DLL CPLJSONObject
60{
61 friend class CPLJSONArray;
62 friend class CPLJSONDocument;
63
64 public:
68 enum class Type
69 {
70 Unknown,
71 Null,
72 Object,
73 Array,
74 Boolean,
75 String,
76 Integer,
77 Long,
78 Double
79 };
80
84 enum class PrettyFormat
85 {
86 Plain,
87 Spaced,
88 Pretty
89 };
90
91 public:
94 explicit CPLJSONObject(const std::string &osName,
95 const CPLJSONObject &oParent);
96 explicit CPLJSONObject(std::nullptr_t);
97 explicit CPLJSONObject(const std::string &osVal);
98 explicit CPLJSONObject(const char *pszValue);
99 explicit CPLJSONObject(bool bVal);
100 explicit CPLJSONObject(int nVal);
101 explicit CPLJSONObject(int64_t nVal);
102 explicit CPLJSONObject(uint64_t nVal);
103 explicit CPLJSONObject(double dfVal);
105 CPLJSONObject(const CPLJSONObject &other);
107 CPLJSONObject &operator=(const CPLJSONObject &other);
108 CPLJSONObject &operator=(CPLJSONObject &&other);
109 CPLJSONObject &operator=(CPLJSONArray &&other);
110
111 // This method is not thread-safe
112 CPLJSONObject Clone() const;
113
114 private:
115 explicit CPLJSONObject(const std::string &osName, JSONObjectH poJsonObject);
118 public:
119 // setters
120 void Add(const std::string &osName, const std::string &osValue);
121#if defined(DOXYGEN_SKIP) || __cplusplus >= 201703L || \
122 (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
123
124 void Add(const std::string &osName, std::string_view svValue);
125#endif
126 void Add(const std::string &osName, const char *pszValue);
127 void Add(const std::string &osName, double dfValue);
128 void Add(const std::string &osName, int nValue);
129 void Add(const std::string &osName, GInt64 nValue);
130 void Add(const std::string &osName, uint64_t nValue);
131 void Add(const std::string &osName, const CPLJSONArray &oValue);
132 void Add(const std::string &osName, const CPLJSONObject &oValue);
133 void AddNoSplitName(const std::string &osName, const CPLJSONObject &oValue);
134 void Add(const std::string &osName, bool bValue);
135 void AddNull(const std::string &osName);
136
138 template <class T> void Set(const std::string &osName, const T &val)
139 {
140 Delete(osName);
141 Add(osName, val);
142 }
143
144 void SetNull(const std::string &osName);
145
146 CPLJSONObject operator[](const std::string &osName);
147
150// GCC 9.4 seems to be confused by the template and doesn't realize it
151// returns *this
152#ifdef __GNUC__
153#pragma GCC diagnostic push
154#pragma GCC diagnostic ignored "-Weffc++"
155#endif
156 template <class T> inline CPLJSONObject &operator=(const T &val)
157 {
158 CPLAssert(!m_osKeyForSet.empty());
159 std::string osKeyForSet = m_osKeyForSet;
160 m_osKeyForSet.clear();
161 Set(osKeyForSet, val);
162 return *this;
163 }
164#ifdef __GNUC__
165#pragma GCC diagnostic pop
166#endif
167
168 template <class T>
169 inline CPLJSONObject &operator=(std::initializer_list<T> list);
170
171 JSONObjectH GetInternalHandle() const
172 {
173 return m_poJsonObject;
174 }
175
178 // getters
179 std::string GetString(const std::string &osName,
180 const std::string &osDefault = "") const;
181 double GetDouble(const std::string &osName, double dfDefault = 0.0) const;
182 int GetInteger(const std::string &osName, int nDefault = 0) const;
183 GInt64 GetLong(const std::string &osName, GInt64 nDefault = 0) const;
184 bool GetBool(const std::string &osName, bool bDefault = false) const;
185 std::string ToString(const std::string &osDefault = "") const;
186 double ToDouble(double dfDefault = 0.0) const;
187 int ToInteger(int nDefault = 0) const;
188 GInt64 ToLong(GInt64 nDefault = 0) const;
189 bool ToBool(bool bDefault = false) const;
190 CPLJSONArray ToArray() const;
191 std::string Format(PrettyFormat eFormat) const;
192
193 //
194 void Delete(const std::string &osName);
195 void DeleteNoSplitName(const std::string &osName);
196 CPLJSONArray GetArray(const std::string &osName) const;
197 CPLJSONObject GetObj(const std::string &osName) const;
198 CPLJSONObject GetObjNoSplitName(const std::string &osName) const;
199 CPLJSONObject operator[](const std::string &osName) const;
200 Type GetType() const;
201
203 std::string GetName() const
204 {
205 return m_osKey;
206 }
207
210 std::vector<CPLJSONObject> GetChildren() const;
211 bool IsValid() const;
212 void Deinit();
213
214 protected:
216 CPLJSONObject GetObjectByPath(const std::string &osPath,
217 std::string &osName) const;
220 private:
221 JSONObjectH m_poJsonObject = nullptr;
222 std::string m_osKey{};
223 std::string m_osKeyForSet{};
224};
225
229class CPL_DLL CPLJSONArray : public CPLJSONObject
230{
231 friend class CPLJSONObject;
232 friend class CPLJSONDocument;
233
234 public:
236 CPLJSONArray();
237 explicit CPLJSONArray(const std::string &osName);
238 explicit CPLJSONArray(const CPLJSONObject &other);
239
241 template <class T> static CPLJSONArray Build(std::initializer_list<T> list)
242 {
243 CPLJSONArray oArray;
244 for (const auto &val : list)
245 oArray.Add(val);
246 return oArray;
247 }
248
249 private:
250 explicit CPLJSONArray(const std::string &osName, JSONObjectH poJsonObject);
251
252 class CPL_DLL ConstIterator
253 {
254 const CPLJSONArray &m_oSelf;
255 int m_nIdx;
256 mutable CPLJSONObject m_oObj{};
257
258 public:
259 using iterator_category = std::input_iterator_tag;
260 using value_type = CPLJSONObject;
261 using difference_type = std::ptrdiff_t;
262 using pointer = CPLJSONObject *;
263 using reference = CPLJSONObject &;
264
265 ConstIterator(const CPLJSONArray &oSelf, bool bStart)
266 : m_oSelf(oSelf), m_nIdx(bStart ? 0 : oSelf.Size())
267 {
268 }
269
270 ConstIterator(const ConstIterator &) = default;
271
272 ConstIterator &operator=(const ConstIterator &other)
273 {
274 if (this != &other)
275 {
276 CPLAssert(&m_oSelf == &(other.m_oSelf));
277 m_nIdx = other.m_nIdx;
278 m_oObj = other.m_oObj;
279 }
280 return *this;
281 }
282
283 ~ConstIterator() = default;
284
285 CPLJSONObject &operator*() const
286 {
287 m_oObj = m_oSelf[m_nIdx];
288 return m_oObj;
289 }
290
291 ConstIterator &operator++()
292 {
293 m_nIdx++;
294 return *this;
295 }
296
297 bool operator==(const ConstIterator &it) const
298 {
299 return m_nIdx == it.m_nIdx;
300 }
301
302 bool operator!=(const ConstIterator &it) const
303 {
304 return m_nIdx != it.m_nIdx;
305 }
306 };
307
309 public:
310 int Size() const;
311
313 inline size_t size() const
314 {
315 return static_cast<size_t>(Size());
316 }
317
318 void AddNull();
319 void Add(const CPLJSONObject &oValue);
320 void Add(const std::string &osValue);
321#if defined(DOXYGEN_SKIP) || __cplusplus >= 201703L || \
322 (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
323
324 void Add(std::string_view svValue);
325#endif
326 void Add(const char *pszValue);
327 void Add(double dfValue);
328 void Add(int nValue);
329 void Add(GInt64 nValue);
330 void Add(uint64_t nValue);
331 void Add(bool bValue);
332
333 CPLJSONObject operator[](int nIndex);
334 const CPLJSONObject operator[](int nIndex) const;
335
336 CPLJSONObject operator[](size_t nIndex);
337 const CPLJSONObject operator[](size_t nIndex) const;
338
340 ConstIterator begin() const
341 {
342 return ConstIterator(*this, true);
343 }
344
346 ConstIterator end() const
347 {
348 return ConstIterator(*this, false);
349 }
350};
351
355class CPL_DLL CPLJSONDocument
356{
357 public:
361 CPLJSONDocument(const CPLJSONDocument &other);
362 CPLJSONDocument &operator=(const CPLJSONDocument &other);
364 CPLJSONDocument &operator=(CPLJSONDocument &&other);
367 bool Save(const std::string &osPath) const;
368 std::string SaveAsString() const;
369
370 CPLJSONObject GetRoot();
371 const CPLJSONObject GetRoot() const;
372 void SetRoot(const CPLJSONObject &oRoot);
373 bool Load(const std::string &osPath);
374 bool LoadMemory(const std::string &osStr);
375 bool LoadMemory(const GByte *pabyData, int nLength = -1);
376 bool LoadChunks(const std::string &osPath, size_t nChunkSize = 16384,
377 GDALProgressFunc pfnProgress = nullptr,
378 void *pProgressArg = nullptr);
379 bool LoadUrl(const std::string &osUrl, const char *const *papszOptions,
380 GDALProgressFunc pfnProgress = nullptr,
381 void *pProgressArg = nullptr);
382
383 private:
384 mutable JSONObjectH m_poRootJsonObject;
385};
386
388template <class T>
389inline CPLJSONObject &CPLJSONObject::operator=(std::initializer_list<T> list)
390{
391 return operator=(CPLJSONArray::Build(list));
392}
393
396CPLStringList CPLParseKeyValueJson(const char *pszJson);
397
398#endif // CPL_JSON_H_INCLUDED
The JSONArray class JSON array from JSONDocument.
Definition cpl_json.h:230
int Size() const
Get array size.
Definition cpl_json.cpp:1432
void Add(const CPLJSONObject &oValue)
Add json object to array.
Definition cpl_json.cpp:1456
ConstIterator begin() const
Iterator to first element.
Definition cpl_json.h:340
size_t size() const
Return the size of the array.
Definition cpl_json.h:313
ConstIterator end() const
Iterator to after last element.
Definition cpl_json.h:346
The CPLJSONDocument class Wrapper class around json-c library.
Definition cpl_json.h:356
The CPLJSONArray class holds JSON object from CPLJSONDocument.
Definition cpl_json.h:60
Type
Json object types.
Definition cpl_json.h:69
PrettyFormat
Json object format to string options.
Definition cpl_json.h:85
void Set(const std::string &osName, const T &val)
Change value by key.
Definition cpl_json.h:138
String list class designed around our use of C "char**" string lists.
Definition cpl_string.h:476
#define CPLAssert(expr)
Assert on an expression.
Definition cpl_error.h:353
CPLStringList CPLParseKeyValueJson(const char *pszJson)
Return a string list of key/value pairs extracted from a JSON doc.
Definition cpl_json.cpp:1648
GIntBig GInt64
Signed 64 bit integer type.
Definition cpl_port.h:216
unsigned char GByte
Unsigned byte type.
Definition cpl_port.h:165
Various convenience functions for working with strings and string lists.