JSONParser jp;
+fmt::println("JFW: about to parse \"{}\" => \"{}\"", name, val);
bool is_valid_json = jp.parse(val);
+fmt::println("JFW: kk");
for (const auto& i : tok) {
vector<field_entity> v;
if (vi.append) {
index = f->arr.size();
} else if (index < 0) {
+fmt::println("JFW: index < 0");
index = f->arr.size() + index;
if (index < 0) {
return -EINVAL; /* out of bounds */
}
}
if ((size_t)index >= f->arr.size()) {
+fmt::println("JFW: index resize");
f->arr.resize(index + 1);
}
f = &f->arr[index];
void handle_value(boost::json::value v);
protected:
- // Although the error_code contains useful information, the API constraints require
- // that we throw it out:
- static bool parse_json(std::string_view input, boost::json::value& data_out)
- {
+ /* While basic parsing is straightforward:
data_out = boost::json::parse(input, boost::json::storage_ptr(),
{ .allow_invalid_utf8 = true });
+ ...we need to fit in with the previous parser, which was frankly more tolerant of
+ invalid data than boost.json is out of the box. Therefore, we employ the stream
+ parser, which is slightly more complicated but more flexible; we also try to reinterpret
+ certain kinds of failures as strings, which IMO is fairly naughty... */
+ static bool parse_json(std::string_view input, boost::json::value& data_out)
+ {
+ boost::json::stream_parser p;
+ boost::system::error_code ec;
+
+ std::size_t bytes_written = p.write_some(input, ec);
+
+ if (!ec) {
+ p.finish(ec);
+ data_out = p.release();
+
+ return true;
+ }
- return true;
- }
+fmt::println("JFW: JSON stream parsing failed: {}", ec.message());
+
+ if (boost::json::error::extra_data == ec || bytes_written < input.size()) {
+ // As the failure case is expected to be rare, and originates from
+ // malformed input, we'll try to convert to a string (as some extant
+ // unit tests appear to expect!) and see what's fixable and what's not:
+
+ // ...try again:
+ boost::system::result<std::string> r = boost::json::try_value_to<std::string>(data_out);
+
+ // ...a big fib, but tolerate the questionable input:
+ if(r) {
+ data_out = *r;
+ return true;
+ }
+ }
+
+ throw std::runtime_error(fmt::format(
+ "JSON error at (position {}): {}\n{}\n---", bytes_written, ec.message(), input));
+
+ return false;
+ }
public:
JSONObj() = default;
}
bool parse(ceph::buffer::list& bl) {
- return parse(bl.c_str(), bl.length());
+ // return parse(bl.c_str(), bl.length());
+ auto ptr = bl.c_str(); // possibly cause compaction, be sure to sequence FIRST
+ return parse(ptr, bl.length());
}
[[deprecated("this may not be reliable")]] bool parse_file(const std::filesystem::path file_name);