Skip to content

Commit

Permalink
Merge pull request dropbox#55 from Dushistov/parse_not_full_json
Browse files Browse the repository at this point in the history
Parse half ready json
  • Loading branch information
j4cbo committed May 3, 2016
2 parents a1409a9 + 33bca8e commit 8452587
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 2 deletions.
5 changes: 4 additions & 1 deletion json11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -735,15 +735,18 @@ Json Json::parse(const string &in, string &err, JsonParse strategy) {

// Documented in json11.hpp
vector<Json> Json::parse_multi(const string &in,
std::string::size_type &parser_stop_pos,
string &err,
JsonParse strategy) {
JsonParser parser { in, 0, err, false, strategy };

parser_stop_pos = 0;
vector<Json> json_vec;
while (parser.i != in.size() && !parser.failed) {
json_vec.push_back(parser.parse_json(0));
// Check for another object
parser.consume_garbage();
if (!parser.failed)
parser_stop_pos = parser.i;
}
return json_vec;
}
Expand Down
9 changes: 9 additions & 0 deletions json11.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,18 @@ class Json final {
// Parse multiple objects, concatenated or separated by whitespace
static std::vector<Json> parse_multi(
const std::string & in,
std::string::size_type & parser_stop_pos,
std::string & err,
JsonParse strategy = JsonParse::STANDARD);

static inline std::vector<Json> parse_multi(
const std::string & in,
std::string & err,
JsonParse strategy = JsonParse::STANDARD) {
std::string::size_type parser_stop_pos;
return parse_multi(in, parser_stop_pos, err, strategy);
}

bool operator== (const Json &rhs) const;
bool operator< (const Json &rhs) const;
bool operator!= (const Json &rhs) const { return !(*this == rhs); }
Expand Down
36 changes: 35 additions & 1 deletion test.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
#ifdef NDEBUG
#undef NDEBUG//at now assert will work even in Release build
#endif
#include <cassert>
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <sstream>
#include "json11.hpp"
#include <cassert>
#include <list>
#include <set>
#include <unordered_map>
#include <algorithm>

using namespace json11;
using std::string;
Expand Down Expand Up @@ -183,6 +187,36 @@ int main(int argc, char **argv) {
assert(nested_array.array_items()[0].is_array());
assert(nested_array.array_items()[0].array_items().size() == 3);

{
const std::string good_json = R"( {"k1" : "v1"})";
const std::string bad_json1 = good_json + " {";
const std::string bad_json2 = good_json + R"({"k2":"v2", "k3":[)";
struct TestMultiParse {
std::string input;
std::string::size_type expect_parser_stop_pos;
size_t expect_not_empty_elms_count;
Json expect_parse_res;
} tests[] = {
{" {", 0, 0, {}},
{good_json, good_json.size(), 1, Json(std::map<string, string>{ { "k1", "v1" } })},
{bad_json1, good_json.size() + 1, 1, Json(std::map<string, string>{ { "k1", "v1" } })},
{bad_json2, good_json.size(), 1, Json(std::map<string, string>{ { "k1", "v1" } })},
{"{}", 2, 1, Json::object{}},
};
for (const auto &tst : tests) {
std::string::size_type parser_stop_pos;
std::string err;
auto res = Json::parse_multi(tst.input, parser_stop_pos, err);
assert(parser_stop_pos == tst.expect_parser_stop_pos);
assert(
std::count_if(res.begin(), res.end(),
[](const Json& j) { return !j.is_null(); })
== tst.expect_not_empty_elms_count);
if (!res.empty()) {
assert(tst.expect_parse_res == res[0]);
}
}
}
Json my_json = Json::object {
{ "key1", "value1" },
{ "key2", false },
Expand Down

0 comments on commit 8452587

Please sign in to comment.