mirror of
https://github.com/nlohmann/json.git
synced 2026-07-12 13:35:13 +00:00
226 lines
9.8 KiB
Markdown
226 lines
9.8 KiB
Markdown
# Frequently Asked Questions (FAQ)
|
|
|
|
## Known bugs
|
|
|
|
### Brace initialization yields arrays
|
|
|
|
Question
|
|
|
|
Why does
|
|
|
|
```
|
|
json j{true};
|
|
```
|
|
|
|
and
|
|
|
|
```
|
|
json j(true);
|
|
```
|
|
|
|
yield different results (`[true]` vs. `true`)?
|
|
|
|
This is a known issue, and -- even worse -- the behavior differs between GCC and Clang. The "culprit" for this is the library's constructor overloads for initializer lists to allow syntax like
|
|
|
|
```
|
|
json array = {1, 2, 3, 4};
|
|
```
|
|
|
|
for arrays and
|
|
|
|
```
|
|
json object = {{"one", 1}, {"two", 2}};
|
|
```
|
|
|
|
for objects.
|
|
|
|
Tip
|
|
|
|
To avoid any confusion and ensure portable code, **do not** use brace initialization with the types `basic_json`, `json`, or `ordered_json` unless you want to create an object or array as shown in the examples above.
|
|
|
|
To explicitly create a single-element array, use `json::array({value})`:
|
|
|
|
```
|
|
json j = json::array({true}); // [true]
|
|
```
|
|
|
|
**Opt-in copy semantics (since version 3.12.0)**
|
|
|
|
If you define `JSON_BRACE_INIT_COPY_SEMANTICS` to `1` before including the library, single-element brace initialization is treated as copy/move instead of creating a single-element array:
|
|
|
|
```
|
|
#define JSON_BRACE_INIT_COPY_SEMANTICS 1
|
|
#include <nlohmann/json.hpp>
|
|
|
|
json obj = {{"key", "value"}};
|
|
json j{obj}; // -> {"key":"value"} (copy, not array)
|
|
```
|
|
|
|
Without the macro (default behavior), `json j{obj}` creates `[{"key":"value"}]`. This opt-in macro fixes issue #5074 while preserving backwards compatibility for existing code.
|
|
|
|
## Limitations
|
|
|
|
### Relaxed parsing
|
|
|
|
Question
|
|
|
|
Can you add an option to ignore trailing commas?
|
|
|
|
This library does not support any feature that would jeopardize interoperability.
|
|
|
|
### Parse errors reading non-ASCII characters
|
|
|
|
Questions
|
|
|
|
- Why is the parser complaining about a Chinese character?
|
|
- Does the library support Unicode?
|
|
- I get an exception `[json.exception.parse_error.101] parse error at line 1, column 53: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '"Testé$')"`
|
|
|
|
The library supports **Unicode input** as follows:
|
|
|
|
- Only **UTF-8** encoded input is supported, which is the default encoding for JSON, according to [RFC 8259](https://tools.ietf.org/html/rfc8259.html#section-8.1).
|
|
- `std::u16string` and `std::u32string` can be parsed, assuming UTF-16 and UTF-32 encoding, respectively. These encodings are not supported when reading from files or other input containers.
|
|
- Other encodings such as Latin-1 or ISO 8859-1 are **not** supported and will yield parse or serialization errors.
|
|
- The library will not replace [Unicode noncharacters](http://www.unicode.org/faq/private_use.html#nonchar1).
|
|
- Invalid surrogates (e.g., incomplete pairs such as `\uDEAD`) will yield parse errors.
|
|
- The strings stored in the library are UTF-8 encoded. When using the default string type (`std::string`), note that its length/size functions return the number of stored bytes rather than the number of characters or glyphs.
|
|
- When you store strings with different encodings in the library, calling [`dump()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a50ec80b02d0f3f51130d4abb5d1cfdc5.html#a50ec80b02d0f3f51130d4abb5d1cfdc5) may throw an exception unless `json::error_handler_t::replace` or `json::error_handler_t::ignore` are used as error handlers.
|
|
|
|
In most cases, the parser is right to complain, because the input is not UTF-8 encoded. This is especially true for Microsoft Windows, where Latin-1 or ISO 8859-1 is often the standard encoding.
|
|
|
|
### Wide string handling
|
|
|
|
Question
|
|
|
|
Why are wide strings (e.g., `std::wstring`) dumped as arrays of numbers?
|
|
|
|
As described [above](#parse-errors-reading-non-ascii-characters), the library assumes UTF-8 as encoding. To store a wide string, you need to change the encoding.
|
|
|
|
Example
|
|
|
|
```
|
|
#include <codecvt> // codecvt_utf8
|
|
#include <locale> // wstring_convert
|
|
|
|
// encoding function
|
|
std::string to_utf8(std::wstring& wide_string)
|
|
{
|
|
static std::wstring_convert<std::codecvt_utf8<wchar_t>> utf8_conv;
|
|
return utf8_conv.to_bytes(wide_string);
|
|
}
|
|
|
|
json j;
|
|
std::wstring ws = L"車B1234 こんにちは";
|
|
|
|
j["original"] = ws;
|
|
j["encoded"] = to_utf8(ws);
|
|
|
|
std::cout << j << std::endl;
|
|
```
|
|
|
|
The result is:
|
|
|
|
```
|
|
{
|
|
"encoded": "車B1234 こんにちは",
|
|
"original": [36554, 66, 49, 50, 51, 52, 32, 12371, 12435, 12395, 12385, 12399]
|
|
}
|
|
```
|
|
|
|
## Usage
|
|
|
|
### Thread safety
|
|
|
|
Question
|
|
|
|
Is `basic_json` thread-safe?
|
|
|
|
No. `basic_json` provides no built-in synchronization, the same as `std::map` or `std::vector`. Concurrent reads of the same value from multiple threads are safe, as are concurrent (non-overlapping) accesses to independent `json` objects. However, any concurrent write to a `json` object -- or a concurrent read while another thread writes to the same object -- is a data race and requires external synchronization (e.g., a `std::mutex`) by the caller.
|
|
|
|
### Schema validation
|
|
|
|
Question
|
|
|
|
Does this library support JSON Schema validation?
|
|
|
|
Not directly, but the companion project [json-schema-validator](https://github.com/pboettch/json-schema-validator) builds JSON Schema (draft 4, 6, 7, and 2019-09) validation on top of this library and is a common recommendation for this use case.
|
|
|
|
## Exceptions
|
|
|
|
### Parsing without exceptions
|
|
|
|
Question
|
|
|
|
Is it possible to indicate a parse error without throwing an exception?
|
|
|
|
Yes, see [Parsing and exceptions](https://json.nlohmann.me/features/parsing/parse_exceptions/index.md).
|
|
|
|
### Key name in exceptions
|
|
|
|
Question
|
|
|
|
Can I get the key of the object item that caused an exception?
|
|
|
|
Yes, you can. Please define the symbol [`JSON_DIAGNOSTICS`](https://json.nlohmann.me/api/macros/json_diagnostics/index.md) to get [extended diagnostics messages](https://json.nlohmann.me/home/exceptions/#extended-diagnostic-messages).
|
|
|
|
## Serialization issues
|
|
|
|
### Number precision
|
|
|
|
Question
|
|
|
|
- It seems that precision is lost when serializing a double.
|
|
- Can I change the precision for floating-point serialization?
|
|
|
|
The library uses `std::numeric_limits<number_float_t>::digits10` (15 for IEEE `double`s) digits for serialization. This value is sufficient to guarantee roundtripping. If one uses more than this number of digits of precision, then string -> value -> string is not guaranteed to round-trip.
|
|
|
|
[cppreference.com](https://en.cppreference.com/w/cpp/types/numeric_limits/digits10)
|
|
|
|
The value of `std::numeric_limits<T>::digits10` is the number of base-10 digits that can be represented by the type T without change, that is, any number with this many significant decimal digits can be converted to a value of type T and back to decimal form, without change due to rounding or overflow.
|
|
|
|
Tip
|
|
|
|
The website <https://float.exposed> gives a good insight into the internal storage of floating-point numbers.
|
|
|
|
See [this section](https://json.nlohmann.me/features/types/number_handling/#number-serialization) on the library's number handling for more information.
|
|
|
|
### Using JSON values with `std::format` or `fmt`
|
|
|
|
Question
|
|
|
|
- Can I use `std::format("{}", j)` on a JSON value?
|
|
- Can I use `fmt::format("{}", j)` or `fmt::print("{}", j)` (the [{fmt}](https://github.com/fmtlib/fmt) library) on a JSON value?
|
|
|
|
`std::format` works out of the box since version 3.13.0, as long as the standard library provides `<format>` (see [`JSON_HAS_STD_FORMAT`](https://json.nlohmann.me/api/macros/json_has_std_format/index.md)); see [`std::formatter<basic_json>`](https://json.nlohmann.me/api/basic_json/std_formatter/index.md) for details, including the `"{:#}"` pretty-print spec, indent widths (`"{:2}"`), and custom indent characters (`"{:.>#}"`).
|
|
|
|
For `fmt`, the library ships [`format_as`](https://json.nlohmann.me/api/basic_json/format_as/index.md), a small customization point `fmt` looks for via argument-dependent lookup. It only has an effect on fmt 10.0.0 through 11.0.2 — from fmt 11.1.0 onwards, `fmt` no longer picks up a `format_as` overload that returns a `std::string`. On such versions (or any version, if you also want the same `"{:#}"`/width/fill-and-align spec support that `std::formatter<basic_json>` has), define your own `fmt::formatter` specialization; see [`format_as`](https://json.nlohmann.me/api/basic_json/format_as/index.md) for a recipe that mirrors it.
|
|
|
|
If you get ambiguous-overload errors when passing a JSON value to `fmt::format`/`fmt::print` without any `fmt::formatter<json>` specialization in scope, that's `fmt` picking up `basic_json`'s implicit `operator ValueType()` conversion operator (see [#964](https://github.com/nlohmann/json/issues/964) and [#958](https://github.com/nlohmann/json/issues/958)); disabling it via [`JSON_USE_IMPLICIT_CONVERSIONS 0`](https://json.nlohmann.me/api/macros/json_use_implicit_conversions/index.md) avoids the ambiguity.
|
|
|
|
## Compilation issues
|
|
|
|
### Android SDK
|
|
|
|
Question
|
|
|
|
Why does the code not compile with Android SDK?
|
|
|
|
Android defaults to using very old compilers and C++ libraries. To fix this, add the following to your `Application.mk`. This will switch to the LLVM C++ library, the Clang compiler, and enable C++11 and other features disabled by default.
|
|
|
|
```
|
|
APP_STL := c++_shared
|
|
NDK_TOOLCHAIN_VERSION := clang3.6
|
|
APP_CPPFLAGS += -frtti -fexceptions
|
|
```
|
|
|
|
The code compiles successfully with [Android NDK](https://developer.android.com/ndk/index.html?hl=ml), Revision 9 - 11 (and possibly later) and [CrystaX's Android NDK](https://www.crystax.net/en/android/ndk) version 10.
|
|
|
|
### Missing STL function
|
|
|
|
Questions
|
|
|
|
- Why do I get a compilation error `'to_string' is not a member of 'std'` (or similarly, for `strtod` or `strtof`)?
|
|
- Why does the code not compile with MinGW or Android SDK?
|
|
|
|
This is not an issue with the code, but rather with the compiler itself. On Android, see above to build with a newer environment. For MinGW, please refer to [this site](http://tehsausage.com/mingw-to-string) and [this discussion](https://github.com/nlohmann/json/issues/136) for information on how to fix this bug. For Android NDK using `APP_STL := gnustl_static`, please refer to [this discussion](https://github.com/nlohmann/json/issues/219).
|