• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bblanchon / ArduinoJson / 18014952124

25 Sep 2025 05:01PM UTC coverage: 99.32% (-0.1%) from 99.418%
18014952124

push

github

bblanchon
Rewrite all converters

Before: 9802, 8486, 9630, 12418, 9654
After:  9802, 8446, 9630, 12242, 9660
Target: 9800, 8458, 9634, 12290, 9702

37 of 39 new or added lines in 1 file covered. (94.87%)

4 existing lines in 3 files now uncovered.

3945 of 3972 relevant lines covered (99.32%)

10265.19 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.33
/src/ArduinoJson/Variant/ConverterImpl.hpp
1
// ArduinoJson - https://arduinojson.org
2
// Copyright © 2014-2025, Benoit BLANCHON
3
// MIT License
4

5
#pragma once
6

7
#include <ArduinoJson/Json/JsonSerializer.hpp>
8
#include <ArduinoJson/Memory/StringBuilder.hpp>
9
#include <ArduinoJson/Polyfills/utility.hpp>
10
#include <ArduinoJson/Variant/JsonVariantConst.hpp>
11

12
#if ARDUINOJSON_ENABLE_STD_STRING
13
#  include <string>
14
#endif
15

16
#if ARDUINOJSON_ENABLE_STRING_VIEW
17
#  include <string_view>
18
#endif
19

20
ARDUINOJSON_BEGIN_PUBLIC_NAMESPACE
21

22
template <typename T, typename Enable>
23
struct Converter {
24
  static_assert(!detail::is_same<T, char>::value,
25
                "type 'char' is not supported, use 'signed char', 'unsigned "
26
                "char' or another integer type instead");
27

28
  static void toJson(const T& src, JsonVariant dst) {
520✔
29
    // clang-format off
30
    convertToJson(src, dst); // Error here? See https://arduinojson.org/v7/unsupported-set/
520✔
31
    // clang-format on
32
  }
520✔
33

34
  static detail::decay_t<T> fromJson(JsonVariantConst src) {
471✔
35
    static_assert(!detail::is_same<T, char*>::value,
36
                  "type 'char*' is not supported, use 'const char*' instead");
37

38
    // clang-format off
39
    T result; // Error here? See https://arduinojson.org/v7/non-default-constructible/
470✔
40
    convertFromJson(src, result);  // Error here? See https://arduinojson.org/v7/unsupported-as/
471✔
41
    // clang-format on
42
    return result;
471✔
43
  }
×
44

45
  static bool checkJson(JsonVariantConst src) {
25✔
46
    static_assert(!detail::is_same<T, char*>::value,
47
                  "type 'char*' is not supported, use 'const char*' instead");
48

49
    T dummy = T();
25✔
50
    // clang-format off
51
    return canConvertFromJson(src, dummy);  // Error here? See https://arduinojson.org/v7/unsupported-is/
50✔
52
    // clang-format on
53
  }
21✔
54
};
55

56
template <typename T>
57
struct Converter<T, detail::enable_if_t<detail::is_integral<T>::value &&
58
                                        !detail::is_same<bool, T>::value &&
59
                                        !detail::is_same<char, T>::value>>
60
    : private detail::VariantAttorney {
61
  static bool toJson(T src, JsonVariant dst) {
1,433✔
62
    ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
63
    auto data = getData(dst);
1,433✔
64
    auto resources = getResourceManager(dst);
1,433✔
65
    if (!data)
1,433✔
66
      return false;
16✔
67
    detail::VariantImpl::clear(data, resources);
1,417✔
68
    return detail::VariantImpl::setInteger(src, data, resources);
1,417✔
69
  }
70

71
  static T fromJson(JsonVariantConst src) {
202✔
72
    ARDUINOJSON_ASSERT_INTEGER_TYPE_IS_SUPPORTED(T);
73
    return getVariantImpl(src).template asIntegral<T>();
202✔
74
  }
75

76
  static bool checkJson(JsonVariantConst src) {
149✔
77
    return getVariantImpl(src).template isInteger<T>();
149✔
78
  }
79
};
80

81
template <typename T>
82
struct Converter<T, detail::enable_if_t<detail::is_enum<T>::value>>
83
    : private detail::VariantAttorney {
84
  static bool toJson(T src, JsonVariant dst) {
1✔
85
    return dst.set(static_cast<JsonInteger>(src));
1✔
86
  }
87

88
  static T fromJson(JsonVariantConst src) {
1✔
89
    return static_cast<T>(getVariantImpl(src).template asIntegral<int>());
1✔
90
  }
91

92
  static bool checkJson(JsonVariantConst src) {
18✔
93
    return getVariantImpl(src).template isInteger<int>();
18✔
94
  }
95
};
96

97
template <>
98
struct Converter<bool> : private detail::VariantAttorney {
99
  static bool toJson(bool src, JsonVariant dst) {
250✔
100
    auto data = getData(dst);
250✔
101
    auto resources = getResourceManager(dst);
250✔
102
    if (!data)
250✔
103
      return false;
2✔
104
    detail::VariantImpl::clear(data, resources);
248✔
105
    data->setBoolean(src);
248✔
106
    return true;
248✔
107
  }
108

109
  static bool fromJson(JsonVariantConst src) {
1,254✔
110
    return getVariantImpl(src).asBoolean();
1,254✔
111
  }
112

113
  static bool checkJson(JsonVariantConst src) {
38✔
114
    auto data = getData(src);
38✔
115
    return data && data->type == detail::VariantType::Boolean;
38✔
116
  }
117
};
118

119
template <typename T>
120
struct Converter<T, detail::enable_if_t<detail::is_floating_point<T>::value>>
121
    : private detail::VariantAttorney {
122
  static bool toJson(T src, JsonVariant dst) {
73✔
123
    auto data = getData(dst);
73✔
124
    auto resources = getResourceManager(dst);
73✔
125
    if (!data)
73✔
126
      return false;
1✔
127
    detail::VariantImpl::clear(data, resources);
72✔
128
    return detail::VariantImpl::setFloat(src, data, resources);
72✔
129
  }
130

131
  static T fromJson(JsonVariantConst src) {
55✔
132
    return getVariantImpl(src).template asFloat<T>();
55✔
133
  }
134

135
  static bool checkJson(JsonVariantConst src) {
48✔
136
    auto data = getData(src);
48✔
137
    return data && data->isFloat();
48✔
138
  }
139
};
140

141
template <>
142
struct Converter<const char*> : private detail::VariantAttorney {
143
  static void toJson(const char* src, JsonVariant dst) {
65,582✔
144
    auto data = getData(dst);
65,582✔
145
    auto resources = getResourceManager(dst);
65,582✔
146
    if (!data)
65,582✔
NEW
147
      return;
×
148
    detail::VariantImpl::clear(data, resources);
65,582✔
149
    detail::VariantImpl::setString(detail::adaptString(src), data, resources);
65,582✔
150
  }
151

152
  static const char* fromJson(JsonVariantConst src) {
62✔
153
    return getVariantImpl(src).asString().c_str();
62✔
154
  }
155

156
  static bool checkJson(JsonVariantConst src) {
43✔
157
    auto data = getData(src);
43✔
158
    return data && data->isString();
43✔
159
  }
160
};
161

162
template <>
163
struct Converter<JsonString> : private detail::VariantAttorney {
164
  static bool toJson(JsonString src, JsonVariant dst) {
41✔
165
    auto data = getData(dst);
41✔
166
    auto resources = getResourceManager(dst);
41✔
167
    if (!data)
41✔
NEW
168
      return false;
×
169
    detail::VariantImpl::clear(data, resources);
41✔
170
    return detail::VariantImpl::setString(detail::adaptString(src), data,
41✔
171
                                          resources);
41✔
172
  }
173

174
  static JsonString fromJson(JsonVariantConst src) {
521✔
175
    return getVariantImpl(src).asString();
521✔
176
  }
177

178
  static bool checkJson(JsonVariantConst src) {
53✔
179
    auto data = getData(src);
53✔
180
    return data && data->isString();
53✔
181
  }
182
};
183

184
template <typename T>
185
inline detail::enable_if_t<detail::IsString<T>::value, bool> convertToJson(
498✔
186
    const T& src, JsonVariant dst) {
187
  auto data = detail::VariantAttorney::getData(dst);
498✔
188
  auto resources = detail::VariantAttorney::getResourceManager(dst);
498✔
189
  if (!data)
498✔
190
    return false;
5✔
191
  detail::VariantImpl::clear(data, resources);
493✔
192
  return detail::VariantImpl::setString(detail::adaptString(src), data,
493✔
193
                                        resources);
493✔
194
}
195

196
// SerializedValue<std::string>
197
// SerializedValue<String>
198
// SerializedValue<const __FlashStringHelper*>
199
template <typename T>
200
struct Converter<SerializedValue<T>> : private detail::VariantAttorney {
201
  static void toJson(SerializedValue<T> src, JsonVariant dst) {
36✔
202
    auto variant = getVariantImpl(dst);
36✔
203
    variant.clear();
36✔
204
    variant.setRawString(src);
36✔
205
  }
36✔
206
};
207

208
template <>
209
struct Converter<detail::nullptr_t> : private detail::VariantAttorney {
210
  static void toJson(detail::nullptr_t, JsonVariant dst) {
7✔
211
    auto data = getData(dst);
7✔
212
    auto resources = getResourceManager(dst);
7✔
213
    if (data)
7✔
214
      detail::VariantImpl::clear(data, resources);
6✔
215
  }
7✔
216
  static detail::nullptr_t fromJson(JsonVariantConst) {
1✔
217
    return nullptr;
1✔
218
  }
219
  static bool checkJson(JsonVariantConst src) {
3✔
220
    auto data = getData(src);
3✔
221
    return data == 0 || data->type == detail::VariantType::Null;
3✔
222
  }
223
};
224

225
#if ARDUINOJSON_ENABLE_ARDUINO_STREAM
226

227
namespace detail {
228
class StringBuilderPrint : public Print {
229
 public:
230
  StringBuilderPrint(ResourceManager* resources) : copier_(resources) {
8✔
231
    copier_.startString();
8✔
232
  }
8✔
233

234
  void save(VariantData* data) {
4✔
235
    ARDUINOJSON_ASSERT(!overflowed());
236
    copier_.save(data);
4✔
237
  }
4✔
238

239
  size_t write(uint8_t c) {
52✔
240
    copier_.append(char(c));
52✔
241
    return copier_.isValid() ? 1 : 0;
52✔
242
  }
243

244
  size_t write(const uint8_t* buffer, size_t size) {
4✔
245
    for (size_t i = 0; i < size; i++) {
54✔
246
      copier_.append(char(buffer[i]));
52✔
247
      if (!copier_.isValid())
52✔
248
        return i;
2✔
249
    }
250
    return size;
2✔
251
  }
252

253
  bool overflowed() const {
8✔
254
    return !copier_.isValid();
8✔
255
  }
256

257
 private:
258
  StringBuilder copier_;
259
};
260
}  // namespace detail
261

262
inline void convertToJson(const ::Printable& src, JsonVariant dst) {
9✔
263
  auto resources = detail::VariantAttorney::getResourceManager(dst);
9✔
264
  auto data = detail::VariantAttorney::getData(dst);
9✔
265
  if (!resources || !data)
9✔
266
    return;
5✔
267
  detail::VariantImpl::clear(data, resources);
8✔
268
  detail::StringBuilderPrint print(resources);
8✔
269
  src.printTo(print);
8✔
270
  if (print.overflowed())
8✔
271
    return;
4✔
272
  print.save(data);
4✔
273
}
8✔
274

275
#endif
276

277
#if ARDUINOJSON_ENABLE_ARDUINO_STRING
278

279
inline void convertFromJson(JsonVariantConst src, ::String& dst) {
280
  JsonString str = src.as<JsonString>();
281
  if (str)
282
    dst = str.c_str();
283
  else
284
    serializeJson(src, dst);
285
}
286

287
inline bool canConvertFromJson(JsonVariantConst src, const ::String&) {
288
  return src.is<JsonString>();
289
}
290

291
#endif
292

293
#if ARDUINOJSON_ENABLE_STD_STRING
294

295
inline void convertFromJson(JsonVariantConst src, std::string& dst) {
465✔
296
  JsonString str = src.as<JsonString>();
465✔
297
  if (str)
465✔
298
    dst.assign(str.c_str(), str.size());
61✔
299
  else
300
    serializeJson(src, dst);
404✔
301
}
465✔
302

303
inline bool canConvertFromJson(JsonVariantConst src, const std::string&) {
21✔
304
  return src.is<JsonString>();
21✔
305
}
306

307
#endif
308

309
#if ARDUINOJSON_ENABLE_STRING_VIEW
310

311
inline void convertFromJson(JsonVariantConst src, std::string_view& dst) {
5✔
312
  JsonString str = src.as<JsonString>();
5✔
313
  if (str)  // the standard doesn't allow passing null to the constructor
5✔
314
    dst = std::string_view(str.c_str(), str.size());
4✔
315
}
5✔
316

317
inline bool canConvertFromJson(JsonVariantConst src, const std::string_view&) {
2✔
318
  return src.is<JsonString>();
2✔
319
}
320

321
#endif
322

323
template <>
324
struct Converter<JsonArrayConst> : private detail::VariantAttorney {
325
  static void toJson(JsonArrayConst src, JsonVariant dst) {
3✔
326
    if (src.isNull())
3✔
UNCOV
327
      dst.set(nullptr);
×
328
    else
329
      dst.to<JsonArray>().set(src);
3✔
330
  }
3✔
331

332
  static JsonArrayConst fromJson(JsonVariantConst src) {
34✔
333
    return JsonArrayConst(getData(src), getResourceManager(src));
34✔
334
  }
335

336
  static bool checkJson(JsonVariantConst src) {
80✔
337
    auto data = getData(src);
80✔
338
    return data && data->type == detail::VariantType::Array;
80✔
339
  }
340
};
341

342
template <>
343
struct Converter<JsonArray> : private detail::VariantAttorney {
344
  static void toJson(JsonVariantConst src, JsonVariant dst) {
11✔
345
    if (src.isNull())
11✔
346
      dst.set(nullptr);
1✔
347
    else
348
      dst.to<JsonArray>().set(src);
10✔
349
  }
11✔
350

351
  static JsonArray fromJson(JsonVariant src) {
76✔
352
    return JsonArray(getData(src), getResourceManager(src));
76✔
353
  }
354

355
  static bool checkJson(JsonVariant src) {
17✔
356
    auto data = getData(src);
17✔
357
    return data && data->type == detail::VariantType::Array;
17✔
358
  }
359
};
360

361
template <>
362
struct Converter<JsonObjectConst> : private detail::VariantAttorney {
363
  static void toJson(JsonVariantConst src, JsonVariant dst) {
9✔
364
    if (src.isNull())
9✔
UNCOV
365
      dst.set(nullptr);
×
366
    else
367
      dst.to<JsonObject>().set(src);
9✔
368
  }
9✔
369

370
  static JsonObjectConst fromJson(JsonVariantConst src) {
35✔
371
    return JsonObjectConst(getData(src), getResourceManager(src));
35✔
372
  }
373

374
  static bool checkJson(JsonVariantConst src) {
304✔
375
    auto data = getData(src);
304✔
376
    return data && data->type == detail::VariantType::Object;
304✔
377
  }
378
};
379

380
template <>
381
struct Converter<JsonObject> : private detail::VariantAttorney {
382
  static void toJson(JsonVariantConst src, JsonVariant dst) {
18✔
383
    if (src.isNull())
18✔
384
      dst.set(nullptr);
1✔
385
    else
386
      dst.to<JsonObject>().set(src);
17✔
387
  }
18✔
388

389
  static JsonObject fromJson(JsonVariant src) {
103✔
390
    return JsonObject(getData(src), getResourceManager(src));
103✔
391
  }
392

393
  static bool checkJson(JsonVariant src) {
48✔
394
    auto data = getData(src);
48✔
395
    return data && data->type == detail::VariantType::Object;
48✔
396
  }
397
};
398

399
ARDUINOJSON_END_PUBLIC_NAMESPACE
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc