Skip to content

Commit 4b17f90

Browse files
Add ignore_trailing_commas option (#4609)
Added examples and modified the corresponding documents and unit tests. Signed-off-by: chirsz-ever <[email protected]> Co-authored-by: Niels Lohmann <[email protected]>
1 parent 2d9a251 commit 4b17f90

File tree

15 files changed

+380
-142
lines changed

15 files changed

+380
-142
lines changed

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1801,7 +1801,17 @@ This library does not support comments by default. It does so for three reasons:
18011801
18021802
3. It is dangerous for interoperability if some libraries would add comment support while others don't. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this.
18031803

1804-
However, you can pass set parameter `ignore_comments` to true in the `parse` function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace.
1804+
However, you can set set parameter `ignore_comments` to true in the `parse` function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace.
1805+
1806+
### Trailing commas
1807+
1808+
The JSON specification does not allow trailing commas in arrays and objects, and hence this library is treating them as parsing errors by default.
1809+
1810+
Like comments, you can set parameter `ignore_trailing_commas` to true in the `parse` function to ignore trailing commas in arrays and objects. Note that a single comma as the only content of the array or object (`[,]` or `{,}`) is not allowed, and multiple trailing commas (`[1,,]`) are not allowed either.
1811+
1812+
This library does not add trailing commas when serializing JSON data.
1813+
1814+
For more information, see [JSON With Commas and Comments (JWCC)](https://nigeltao.github.io/blog/2021/json-with-commas-comments.html).
18051815

18061816
### Order of object keys
18071817

docs/mkdocs/docs/api/basic_json/accept.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
// (1)
55
template<typename InputType>
66
static bool accept(InputType&& i,
7-
const bool ignore_comments = false);
7+
const bool ignore_comments = false,
8+
const bool ignore_trailing_commas = false);
89

910
// (2)
1011
template<typename IteratorType>
1112
static bool accept(IteratorType first, IteratorType last,
12-
const bool ignore_comments = false);
13+
const bool ignore_comments = false,
14+
const bool ignore_trailing_commas = false);
1315
```
1416
1517
Checks whether the input is valid JSON.
@@ -50,6 +52,10 @@ Unlike the [`parse()`](parse.md) function, this function neither throws an excep
5052
: whether comments should be ignored and treated like whitespace (`#!cpp true`) or yield a parse error
5153
(`#!cpp false`); (optional, `#!cpp false` by default)
5254
55+
`ignore_trailing_commas` (in)
56+
: whether trailing commas in arrays or objects should be ignored and treated like whitespace (`#!cpp true`) or yield a parse error
57+
(`#!cpp false`); (optional, `#!cpp false` by default)
58+
5359
`first` (in)
5460
: iterator to the start of the character range
5561
@@ -102,6 +108,7 @@ A UTF-8 byte order mark is silently ignored.
102108
- Added in version 3.0.0.
103109
- Ignoring comments via `ignore_comments` added in version 3.9.0.
104110
- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.12.0.
111+
- Added `ignore_trailing_commas` in version 3.12.1.
105112
106113
!!! warning "Deprecation"
107114

docs/mkdocs/docs/api/basic_json/parse.md

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ template<typename InputType>
66
static basic_json parse(InputType&& i,
77
const parser_callback_t cb = nullptr,
88
const bool allow_exceptions = true,
9-
const bool ignore_comments = false);
9+
const bool ignore_comments = false,
10+
const bool ignore_trailing_commas = false);
1011

1112
// (2)
1213
template<typename IteratorType>
1314
static basic_json parse(IteratorType first, IteratorType last,
1415
const parser_callback_t cb = nullptr,
1516
const bool allow_exceptions = true,
16-
const bool ignore_comments = false);
17+
const bool ignore_comments = false,
18+
const bool ignore_trailing_commas = false);
1719
```
1820
1921
1. Deserialize from a compatible input.
@@ -56,6 +58,10 @@ static basic_json parse(IteratorType first, IteratorType last,
5658
: whether comments should be ignored and treated like whitespace (`#!cpp true`) or yield a parse error
5759
(`#!cpp false`); (optional, `#!cpp false` by default)
5860
61+
`ignore_trailing_commas` (in)
62+
: whether trailing commas in arrays or objects should be ignored and treated like whitespace (`#!cpp true`) or yield a parse error
63+
(`#!cpp false`); (optional, `#!cpp false` by default)
64+
5965
`first` (in)
6066
: iterator to the start of a character range
6167
@@ -189,6 +195,34 @@ A UTF-8 byte order mark is silently ignored.
189195
--8<-- "examples/parse__allow_exceptions.output"
190196
```
191197
198+
??? example "Effect of `ignore_comments` parameter"
199+
200+
The example below demonstrates the effect of the `ignore_comments` parameter in the `parse()` function.
201+
202+
```cpp
203+
--8<-- "examples/comments.cpp"
204+
```
205+
206+
Output:
207+
208+
```
209+
--8<-- "examples/comments.output"
210+
```
211+
212+
??? example "Effect of `ignore_trailing_commas` parameter"
213+
214+
The example below demonstrates the effect of the `ignore_trailing_commas` parameter in the `parse()` function.
215+
216+
```cpp
217+
--8<-- "examples/trailing_commas.cpp"
218+
```
219+
220+
Output:
221+
222+
```
223+
--8<-- "examples/trailing_commas.output"
224+
```
225+
192226
## See also
193227
194228
- [accept](accept.md) - check if the input is valid JSON
@@ -200,6 +234,7 @@ A UTF-8 byte order mark is silently ignored.
200234
- Overload for contiguous containers (1) added in version 2.0.3.
201235
- Ignoring comments via `ignore_comments` added in version 3.9.0.
202236
- Changed [runtime assertion](../../features/assertions.md) in case of `FILE*` null pointers to exception in version 3.12.0.
237+
- Added `ignore_trailing_commas` in version 3.12.1.
203238
204239
!!! warning "Deprecation"
205240

docs/mkdocs/docs/api/basic_json/sax_parse.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ static bool sax_parse(InputType&& i,
77
SAX* sax,
88
input_format_t format = input_format_t::json,
99
const bool strict = true,
10-
const bool ignore_comments = false);
10+
const bool ignore_comments = false,
11+
const bool ignore_trailing_commas = false);
1112

1213
// (2)
1314
template<class IteratorType, class SAX>
1415
static bool sax_parse(IteratorType first, IteratorType last,
1516
SAX* sax,
1617
input_format_t format = input_format_t::json,
1718
const bool strict = true,
18-
const bool ignore_comments = false);
19+
const bool ignore_comments = false,
20+
const bool ignore_trailing_commas = false);
1921
```
2022
2123
Read from input and generate SAX events
@@ -65,6 +67,10 @@ The SAX event lister must follow the interface of [`json_sax`](../json_sax/index
6567
: whether comments should be ignored and treated like whitespace (`#!cpp true`) or yield a parse error
6668
(`#!cpp false`); (optional, `#!cpp false` by default)
6769
70+
`ignore_trailing_commas` (in)
71+
: whether trailing commas in arrays or objects should be ignored and treated like whitespace (`#!cpp true`) or yield a parse error
72+
(`#!cpp false`); (optional, `#!cpp false` by default)
73+
6874
`first` (in)
6975
: iterator to the start of a character range
7076
@@ -107,6 +113,7 @@ A UTF-8 byte order mark is silently ignored.
107113
108114
- Added in version 3.2.0.
109115
- Ignoring comments via `ignore_comments` added in version 3.9.0.
116+
- Added `ignore_trailing_commas` in version 3.12.1.
110117
111118
!!! warning "Deprecation"
112119
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
#include <iostream>
3+
#include <nlohmann/json.hpp>
4+
5+
using json = nlohmann::json;
6+
7+
int main()
8+
{
9+
std::string s = R"(
10+
{
11+
// update in 2006: removed Pluto
12+
"planets": ["Mercury", "Venus", "Earth", "Mars",
13+
"Jupiter", "Uranus", "Neptune" /*, "Pluto" */]
14+
}
15+
)";
16+
17+
try
18+
{
19+
json j = json::parse(s);
20+
}
21+
catch (json::exception& e)
22+
{
23+
std::cout << e.what() << std::endl;
24+
}
25+
26+
json j = json::parse(s,
27+
/* callback */ nullptr,
28+
/* allow exceptions */ true,
29+
/* ignore_comments */ true);
30+
std::cout << j.dump(2) << '\n';
31+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[json.exception.parse_error.101] parse error at line 3, column 9: syntax error while parsing object key - invalid literal; last read: '<U+000A> {<U+000A> /'; expected string literal
2+
{
3+
"planets": [
4+
"Mercury",
5+
"Venus",
6+
"Earth",
7+
"Mars",
8+
"Jupiter",
9+
"Uranus",
10+
"Neptune"
11+
]
12+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <iostream>
2+
#include <nlohmann/json.hpp>
3+
4+
using json = nlohmann::json;
5+
6+
int main()
7+
{
8+
std::string s = R"(
9+
{
10+
"planets": [
11+
"Mercury",
12+
"Venus",
13+
"Earth",
14+
"Mars",
15+
"Jupiter",
16+
"Uranus",
17+
"Neptune",
18+
]
19+
}
20+
)";
21+
22+
try
23+
{
24+
json j = json::parse(s);
25+
}
26+
catch (json::exception& e)
27+
{
28+
std::cout << e.what() << std::endl;
29+
}
30+
31+
json j = json::parse(s,
32+
/* callback */ nullptr,
33+
/* allow exceptions */ true,
34+
/* ignore_comments */ false,
35+
/* ignore_trailing_commas */ true);
36+
std::cout << j.dump(2) << '\n';
37+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[json.exception.parse_error.101] parse error at line 11, column 9: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal
2+
{
3+
"planets": [
4+
"Mercury",
5+
"Venus",
6+
"Earth",
7+
"Mars",
8+
"Jupiter",
9+
"Uranus",
10+
"Neptune"
11+
]
12+
}

docs/mkdocs/docs/features/comments.md

Lines changed: 5 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ This library does not support comments *by default*. It does so for three reason
1111
1212
3. It is dangerous for interoperability if some libraries add comment support while others do not. Please check [The Harmful Consequences of the Robustness Principle](https://tools.ietf.org/html/draft-iab-protocol-maintenance-01) on this.
1313

14-
However, you can pass set parameter `ignore_comments` to `#!c true` in the parse function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace.
14+
However, you can set parameter `ignore_comments` to `#!cpp true` in the [`parse`](../api/basic_json/parse.md) function to ignore `//` or `/* */` comments. Comments will then be treated as whitespace.
15+
16+
For more information, see [JSON With Commas and Comments (JWCC)](https://nigeltao.github.io/blog/2021/json-with-commas-comments.html).
1517

1618
!!! example
1719

@@ -28,56 +30,11 @@ However, you can pass set parameter `ignore_comments` to `#!c true` in the parse
2830
When calling `parse` without additional argument, a parse error exception is thrown. If `ignore_comments` is set to `#! true`, the comments are ignored during parsing:
2931

3032
```cpp
31-
#include <iostream>
32-
#include "json.hpp"
33-
34-
using json = nlohmann::json;
35-
36-
int main()
37-
{
38-
std::string s = R"(
39-
{
40-
// update in 2006: removed Pluto
41-
"planets": ["Mercury", "Venus", "Earth", "Mars",
42-
"Jupiter", "Uranus", "Neptune" /*, "Pluto" */]
43-
}
44-
)";
45-
46-
try
47-
{
48-
json j = json::parse(s);
49-
}
50-
catch (json::exception &e)
51-
{
52-
std::cout << e.what() << std::endl;
53-
}
54-
55-
json j = json::parse(s,
56-
/* callback */ nullptr,
57-
/* allow exceptions */ true,
58-
/* ignore_comments */ true);
59-
std::cout << j.dump(2) << '\n';
60-
}
33+
--8<-- "examples/comments.cpp"
6134
```
6235

6336
Output:
6437

6538
```
66-
[json.exception.parse_error.101] parse error at line 3, column 9:
67-
syntax error while parsing object key - invalid literal;
68-
last read: '<U+000A> {<U+000A> /'; expected string literal
69-
```
70-
71-
```json
72-
{
73-
"planets": [
74-
"Mercury",
75-
"Venus",
76-
"Earth",
77-
"Mars",
78-
"Jupiter",
79-
"Uranus",
80-
"Neptune"
81-
]
82-
}
39+
--8<-- "examples/comments.output"
8340
```
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Trailing Commas
2+
3+
Like [comments](comments.md), this library does not support trailing commas in arrays and objects *by default*.
4+
5+
You can set parameter `ignore_trailing_commas` to `#!cpp true` in the [`parse`](../api/basic_json/parse.md) function to allow trailing commas in arrays and objects. Note that a single comma as the only content of the array or object (`[,]` or `{,}`) is not allowed, and multiple trailing commas (`[1,,]`) are not allowed either.
6+
7+
This library does not add trailing commas when serializing JSON data.
8+
9+
For more information, see [JSON With Commas and Comments (JWCC)](https://nigeltao.github.io/blog/2021/json-with-commas-comments.html).
10+
11+
!!! example
12+
13+
Consider the following JSON with trailing commas.
14+
15+
```json
16+
{
17+
"planets": [
18+
"Mercury",
19+
"Venus",
20+
"Earth",
21+
"Mars",
22+
"Jupiter",
23+
"Uranus",
24+
"Neptune",
25+
]
26+
}
27+
```
28+
29+
When calling `parse` without additional argument, a parse error exception is thrown. If `ignore_trailing_commas` is set to `#! true`, the trailing commas are ignored during parsing:
30+
31+
```cpp
32+
--8<-- "examples/trailing_commas.cpp"
33+
```
34+
35+
Output:
36+
37+
```
38+
--8<-- "examples/trailing_commas.output"
39+
```

0 commit comments

Comments
 (0)