kazuho/picojson

Add utility `parse` function that takes a `std::string` as input

Closed this issue · 3 comments

In my application I always have a std::string and want to parse it into a picojson::value.

@kazuho How about adding this utility function?

#include <string>
#include <sstream>
#include "picojson.h"

std::string parse(picojson::value& out, const std::string& in) {
    std::istringstream is(in);
    std::string err = picojson::parse(out, is);
    return err;
}

int main() {
    // Say you have a `std::string`
    std::string input = "[1, 2, ,3]";

    // Wouldn't it be nice to have a convenience function to parse
    // it without having to add an `sstream` include 
    // and creating a temp `istringstream` variable?
    picojson::value val;
    std::string err = parse(val, input);

    std::cout << err << std::endl;
    std::cout << val.serialize() << std::endl;
    return 0;
}

Actually often I don't care about the error ... in this case the most convenient thing would be

picojson::value val = picojson::parse(std::string input);

so this is a second utility function I'm proposing.

(for my applications performance doesn't matter ... I just don't want to type a lot and spend time looking up which include I need for istringstream.)

Thank you for the PR. I am sorry but I am not interested in adding a function that ignores errors to picojson.

Of course you are free to do whatever in your application. And if you do not want to handle errors in every piece of your code, I would suggest to write a wrapper around picojson that throws std::runtime_error in case an error is returned instead of just ignoring the error.

BTW you do not need to use std::istream to parse a std::string. By using the parse function that accepts the iterators, you can write like:

std::string input = "{ ... }"; // json string
picojson::value value;

picojson::parse(&value, input.begin(), input.end(), &error);

I didn't realise I could avoid the std::istream ... thanks for that tip.
In case someone else finds this useful because they also have to write a ton of parse statements in their code and want it to be short ... here's a super-simple parse function:

  inline value parse(const std::string s) {
    std::string err;
    value val;
    parse(val, s.begin(), s.end(), &err);
    if (! err.empty()) {
      throw std::runtime_error(err);
    }
    return val;
  }

I've started adding utility functions to my copy of picojson.h.
Obviously I'd prefer to have more helper functions like that directly available, but OK ... closing this issue.

@cdeil 👍 for sharing the code snippet.

As a note, you could create a separate header file and write like the following. By doing so, you do not need to modify picojson.h (and thus it would be easier to follow the upstream changes).

#include "picojson.h"

namespace picojson {
  inline value parse(const std::string& s) {
    std::string err;
    value val;
    parse(val, s.begin(), s.end(), &err);
    if (! err.empty()) {
      throw std::runtime_error(err);
    }
    return val;
  }
}

EDIT: added & to the argument.