Skip to content

Commit 29c0acf

Browse files
committed
Add more specific error for empty input
1 parent edffad0 commit 29c0acf

File tree

5 files changed

+40
-25
lines changed

5 files changed

+40
-25
lines changed

docs/mkdocs/docs/home/exceptions.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ Note that [`JSON_THROW_USER`](../api/macros/json_throw_user.md) should leave the
3838

3939
```cpp
4040
#include <iostream>
41-
41+
4242
#define JSON_TRY_USER if(true)
4343
#define JSON_CATCH_USER(exception) if(false)
4444
#define JSON_THROW_USER(exception) \
4545
{std::clog << "Error in " << __FILE__ << ":" << __LINE__ \
4646
<< " (function " << __FUNCTION__ << ") - " \
4747
<< (exception).what() << std::endl; \
4848
std::abort();}
49-
49+
5050
#include <nlohmann/json.hpp>
5151
```
5252

@@ -63,7 +63,7 @@ Exceptions in the library are thrown in the local context of the JSON value they
6363
```cpp
6464
--8<-- "examples/diagnostics_standard.cpp"
6565
```
66-
66+
6767
Output:
6868

6969
```
@@ -81,7 +81,7 @@ As this global context comes at the price of storing one additional pointer per
8181
```cpp
8282
--8<-- "examples/diagnostics_extended.cpp"
8383
```
84-
84+
8585
Output:
8686

8787
```
@@ -116,7 +116,7 @@ Exceptions have ids 1xx.
116116
```cpp
117117
--8<-- "examples/parse_error.cpp"
118118
```
119-
119+
120120
Output:
121121

122122
```
@@ -139,7 +139,7 @@ This error indicates a syntax error while deserializing a JSON text. The error m
139139
No input:
140140

141141
```
142-
[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal
142+
[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON
143143
```
144144

145145
Control character was not escaped:
@@ -368,7 +368,7 @@ Exceptions have ids 2xx.
368368
```cpp
369369
--8<-- "examples/invalid_iterator.cpp"
370370
```
371-
371+
372372
Output:
373373

374374
```
@@ -532,7 +532,7 @@ Exceptions have ids 3xx.
532532
```cpp
533533
--8<-- "examples/type_error.cpp"
534534
```
535-
535+
536536
Output:
537537

538538
```
@@ -726,7 +726,7 @@ The `dump()` function only works with UTF-8 encoded strings; that is, if you ass
726726

727727
- Store the source file with UTF-8 encoding.
728728
- Pass an error handler as last parameter to the `dump()` function to avoid this exception:
729-
- `json::error_handler_t::replace` will replace invalid bytes sequences with `U+FFFD`
729+
- `json::error_handler_t::replace` will replace invalid bytes sequences with `U+FFFD`
730730
- `json::error_handler_t::ignore` will silently ignore invalid byte sequences
731731

732732
### json.exception.type_error.317
@@ -761,7 +761,7 @@ Exceptions have ids 4xx.
761761
```cpp
762762
--8<-- "examples/out_of_range.cpp"
763763
```
764-
764+
765765
Output:
766766

767767
```
@@ -840,7 +840,7 @@ UBJSON and BSON only support integer numbers up to 9223372036854775807.
840840

841841
!!! note
842842

843-
Since version 3.9.0, integer numbers beyond int64 are serialized as high-precision UBJSON numbers, and this exception does not further occur.
843+
Since version 3.9.0, integer numbers beyond int64 are serialized as high-precision UBJSON numbers, and this exception does not further occur.
844844

845845
### json.exception.out_of_range.408
846846

@@ -876,7 +876,7 @@ Exceptions have ids 5xx.
876876
```cpp
877877
--8<-- "examples/other_error.cpp"
878878
```
879-
879+
880880
Output:
881881

882882
```

include/nlohmann/detail/input/parser.hpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,20 @@ class parser
341341
m_lexer.get_token_string(),
342342
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
343343
}
344-
344+
case token_type::end_of_input:
345+
{
346+
if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1)) {
347+
return sax->parse_error(m_lexer.get_position(),
348+
m_lexer.get_token_string(),
349+
parse_error::create(101, m_lexer.get_position(),
350+
"attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
351+
}
352+
}
345353
case token_type::uninitialized:
346354
case token_type::end_array:
347355
case token_type::end_object:
348356
case token_type::name_separator:
349357
case token_type::value_separator:
350-
case token_type::end_of_input:
351358
case token_type::literal_or_value:
352359
default: // the last token was unexpected
353360
{

single_include/nlohmann/json.hpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12441,13 +12441,21 @@ class parser
1244112441
m_lexer.get_token_string(),
1244212442
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
1244312443
}
12444-
12444+
case token_type::end_of_input:
12445+
{
12446+
if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
12447+
{
12448+
return sax->parse_error(m_lexer.get_position(),
12449+
m_lexer.get_token_string(),
12450+
parse_error::create(101, m_lexer.get_position(),
12451+
"attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12452+
}
12453+
}
1244512454
case token_type::uninitialized:
1244612455
case token_type::end_array:
1244712456
case token_type::end_object:
1244812457
case token_type::name_separator:
1244912458
case token_type::value_separator:
12450-
case token_type::end_of_input:
1245112459
case token_type::literal_or_value:
1245212460
default: // the last token was unexpected
1245312461
{

tests/src/unit-diagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ TEST_CASE("Better diagnostics")
7474
SECTION("Parse error")
7575
{
7676
json _;
77-
CHECK_THROWS_WITH_AS(_ = json::parse(""), "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error);
77+
CHECK_THROWS_WITH_AS(_ = json::parse(""), "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error);
7878
}
7979

8080
SECTION("Wrong type in update()")

tests/src/unit-regression1.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -722,7 +722,7 @@ TEST_CASE("regression tests 1")
722722
{
723723
std::ifstream f("file_not_found.json");
724724
json _;
725-
CHECK_THROWS_WITH_AS(_ = json::parse(f), "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
725+
CHECK_THROWS_WITH_AS(_ = json::parse(f), "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
726726
}
727727

728728
SECTION("issue #367 - calling stream at EOF")
@@ -736,7 +736,7 @@ TEST_CASE("regression tests 1")
736736
// ss is not at EOF; this yielded an error before the fix
737737
// (threw basic_string::append). No, it should just throw
738738
// a parse error because of the EOF.
739-
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
739+
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
740740
}
741741

742742
SECTION("issue #367 - behavior of operator>> should more closely resemble that of built-in overloads")
@@ -745,7 +745,7 @@ TEST_CASE("regression tests 1")
745745
{
746746
std::stringstream ss;
747747
json j;
748-
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
748+
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
749749
}
750750

751751
SECTION("(whitespace)")
@@ -765,7 +765,7 @@ TEST_CASE("regression tests 1")
765765
CHECK_NOTHROW(ss >> j);
766766
CHECK(j == 111);
767767

768-
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
768+
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
769769
}
770770

771771
SECTION("one value + whitespace")
@@ -788,7 +788,7 @@ TEST_CASE("regression tests 1")
788788
CHECK_NOTHROW(ss >> j);
789789
CHECK(j == 333);
790790

791-
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
791+
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
792792
}
793793

794794
SECTION("three values")
@@ -803,7 +803,7 @@ TEST_CASE("regression tests 1")
803803
CHECK_NOTHROW(ss >> j);
804804
CHECK(j == 333);
805805

806-
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
806+
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
807807
}
808808

809809
SECTION("literals without whitespace")
@@ -820,7 +820,7 @@ TEST_CASE("regression tests 1")
820820
CHECK_NOTHROW(ss >> j);
821821
CHECK(j == "");
822822

823-
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
823+
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
824824
}
825825

826826
SECTION("example from #529")
@@ -833,7 +833,7 @@ TEST_CASE("regression tests 1")
833833
CHECK_NOTHROW(ss >> j);
834834
CHECK(j == json({{"three", 3}}));
835835

836-
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
836+
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error&);
837837
}
838838

839839
SECTION("second example from #529")

0 commit comments

Comments
 (0)