mirror of
https://github.com/nlohmann/json.git
synced 2026-10-28 08:45:43 +00:00
docs: write std::chrono durations as unit/value objects; reword a title with escaped quotes (#5911)
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
1 parent
ffd4242dc2
commit
fe231dc692
4 files changed
+55
-9
No files matched your search
@@ -1,9 +1,38 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
// the name of a period; extend the list for the periods you use
|
||||||
|
template <typename Period> const char* unit_name();
|
||||||
|
template <> const char* unit_name<std::nano>()
|
||||||
|
{
|
||||||
|
return "ns";
|
||||||
|
}
|
||||||
|
template <> const char* unit_name<std::micro>()
|
||||||
|
{
|
||||||
|
return "us";
|
||||||
|
}
|
||||||
|
template <> const char* unit_name<std::milli>()
|
||||||
|
{
|
||||||
|
return "ms";
|
||||||
|
}
|
||||||
|
template <> const char* unit_name<std::ratio<1>>()
|
||||||
|
{
|
||||||
|
return "s";
|
||||||
|
}
|
||||||
|
template <> const char* unit_name<std::ratio<60>>()
|
||||||
|
{
|
||||||
|
return "min";
|
||||||
|
}
|
||||||
|
template <> const char* unit_name<std::ratio<3600>>()
|
||||||
|
{
|
||||||
|
return "h";
|
||||||
|
}
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
{
|
{
|
||||||
template <typename Rep, typename Period>
|
template <typename Rep, typename Period>
|
||||||
@@ -11,12 +40,16 @@ struct adl_serializer<std::chrono::duration<Rep, Period>>
|
|||||||
{
|
{
|
||||||
static void to_json(json& j, const std::chrono::duration<Rep, Period>& d)
|
static void to_json(json& j, const std::chrono::duration<Rep, Period>& d)
|
||||||
{
|
{
|
||||||
j = d.count();
|
j = {{"unit", unit_name<Period>()}, {"value", d.count()}};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void from_json(const json& j, std::chrono::duration<Rep, Period>& d)
|
static void from_json(const json& j, std::chrono::duration<Rep, Period>& d)
|
||||||
{
|
{
|
||||||
d = std::chrono::duration<Rep, Period>(j.get<Rep>());
|
if (j.at("unit").get<std::string>() != unit_name<Period>())
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("unexpected unit " + j.at("unit").dump());
|
||||||
|
}
|
||||||
|
d = std::chrono::duration<Rep, Period>(j.at("value").get<Rep>());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -41,11 +74,21 @@ int main()
|
|||||||
|
|
||||||
std::cout << std::boolalpha;
|
std::cout << std::boolalpha;
|
||||||
|
|
||||||
// the unit is not part of the JSON value
|
// the unit is part of the JSON value
|
||||||
const json timeout = milliseconds(1500);
|
const json timeout = milliseconds(1500);
|
||||||
std::cout << "duration: " << timeout << '\n';
|
std::cout << "duration: " << timeout << '\n';
|
||||||
std::cout << "as milliseconds: " << timeout.get<milliseconds>().count() << '\n';
|
std::cout << "as milliseconds: " << timeout.get<milliseconds>().count() << '\n';
|
||||||
|
|
||||||
|
// reading with a different unit is rejected
|
||||||
|
try
|
||||||
|
{
|
||||||
|
timeout.get<seconds>();
|
||||||
|
}
|
||||||
|
catch (const std::invalid_argument& e)
|
||||||
|
{
|
||||||
|
std::cout << "error: " << e.what() << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
// a system_clock time point is the time since the Unix epoch
|
// a system_clock time point is the time since the Unix epoch
|
||||||
const time_point<system_clock, milliseconds> t(milliseconds(1700000000123));
|
const time_point<system_clock, milliseconds> t(milliseconds(1700000000123));
|
||||||
const json stamp = t;
|
const json stamp = t;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
duration: 1500
|
duration: {"unit":"ms","value":1500}
|
||||||
as milliseconds: 1500
|
as milliseconds: 1500
|
||||||
time point: 1700000000123
|
error: unexpected unit "ms"
|
||||||
|
time point: {"unit":"ms","value":1700000000123}
|
||||||
round trip: true
|
round trip: true
|
||||||
@@ -92,8 +92,10 @@ to choose the alternative.
|
|||||||
|
|
||||||
## `std::chrono`
|
## `std::chrono`
|
||||||
|
|
||||||
A duration is written as its count and read back with the same representation and period. The **unit is not part of
|
A duration is written as an object with the keys `unit` and `value`, for example `{"unit": "ms", "value": 1500}`, so
|
||||||
the JSON value**, so document it, for example in the member name (`timeout_ms`):
|
the JSON value is self-describing. The serializer names the unit of the period (`ns`, `us`, `ms`, `s`, `min`, `h`;
|
||||||
|
extend the list for other periods), and the deserializer rejects a value whose unit differs from the requested
|
||||||
|
duration type instead of silently misreading it:
|
||||||
|
|
||||||
??? example "Example: serialize durations and system_clock time points"
|
??? example "Example: serialize durations and system_clock time points"
|
||||||
|
|
||||||
@@ -107,7 +109,7 @@ the JSON value**, so document it, for example in the member name (`timeout_ms`):
|
|||||||
--8<-- "examples/type_recipes_chrono.output"
|
--8<-- "examples/type_recipes_chrono.output"
|
||||||
```
|
```
|
||||||
|
|
||||||
A `system_clock::time_point` with millisecond precision is written as the number of milliseconds since the Unix epoch.
|
A `system_clock::time_point` with millisecond precision is written as the duration since the Unix epoch, that is, as an object with `unit` and `value`.
|
||||||
The time point serializer is limited to `system_clock`,
|
The time point serializer is limited to `system_clock`,
|
||||||
because the epoch of other clocks (for example `steady_clock`) has no meaning outside the running program.
|
because the epoch of other clocks (for example `steady_clock`) has no meaning outside the running program.
|
||||||
|
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ This error indicates a syntax error while deserializing a JSON text. The error m
|
|||||||
- Make sure the input is correctly read. Try to write the input to standard output to check if, for instance, the input file was successfully opened.
|
- Make sure the input is correctly read. Try to write the input to standard output to check if, for instance, the input file was successfully opened.
|
||||||
- Paste the input to a JSON validator like <https://jsonlint.com> or a tool like [jq](https://jqlang.github.io/jq/).
|
- Paste the input to a JSON validator like <https://jsonlint.com> or a tool like [jq](https://jqlang.github.io/jq/).
|
||||||
|
|
||||||
??? info "Parsing a file fails at line 1, column 1 (or \"unexpected end of input\")"
|
??? info "Parsing a file fails at line 1, column 1 (unexpected end of input)"
|
||||||
|
|
||||||
The messages `attempting to parse an empty input` (since version 3.11.3) and `unexpected end of input` (also the message of
|
The messages `attempting to parse an empty input` (since version 3.11.3) and `unexpected end of input` (also the message of
|
||||||
earlier versions for an empty input) at the very start of the input mean
|
earlier versions for an empty input) at the very start of the input mean
|
||||||
|
|||||||
Reference in new issue
Block a user