Git Product home page Git Product logo

picojson's Introduction

PicoJSON - a C++ JSON parser / serializer

Copyright © 2009-2010 Cybozu Labs, Inc. Copyright © 2011-2015 Kazuho Oku

Licensed under 2-clause BSD license

Version

1.3.1-dev Build Status

Introduction

PicoJSON is a tiny JSON parser / serializer for C++ with following properties:

  • header-file only
  • no external dependencies (only uses standard C++ libraries)
  • STL-frendly (arrays are represented by using std::vector, objects are std::map)
  • provides both pull interface and streaming (event-based) interface

Reading JSON using the pull interface

There are several ways to use the pull (DOM-like) interface of picojson.

The easiest way is to use the two-argument parse function.

std::string json = "[ \"hello JSON\" ]";
picojson::value v;
std::string err = picojson::parse(v, json);
if (! err.empty()) {
  std:cerr << err << std::endl;
}

Four-argument parse function accepts a pair of iterators, and returns the end position of the input.

const char* json = "{\"a\":1}";
picojson::value v;
std::string err;
const char* json_end = picojson::parse(v, json, json + strlen(json), &err);
if (! err.empty()) {
  std::cerr << err << std::endl;
}
std::istream_iterator input(std::cin);
picojson::value v;
std::string err;
input = picojson::parse(v, input, std::istream_iterator(), &err);
if (! err.empty()) {
  std::cerr << err << std::endl;
}

It is also possible to use the >> operator to parse the input, however this interface is not thread-safe.

picosjon::value v;
std::cin >> v;
std::string err = picojson::get_last_error();

Accessing the values

Values of a JSON object is represented as instances of picojson::value class.

namespace picojson {

  class value {
    ...

  public:

    typedef std::vector<value> array;
    typedef std::map<std::string, value> object;

    value();                               // create a null object
    explicit value(bool b);                // create a boolean object
    explicit value(double n);              // create a number object
    explicit value(const std::string& s);  // create a string object
    explicit value(const array& a);        // create an array object
    explicit value(const object& o);       // create an "object"

    bool is<picojson::null>() const;       // check if the object is "null"

    bool is<bool>() const;                 // check if the object is a boolean
    const bool& get<bool>() const;         // const accessor (usable only if the object is a boolean)
    bool& get<bool>();                     // non-const accessor (usable only if the object is a boolean)

    bool is<double>() const;               // check if the object is a number
    const double& get<double>() const;     // const accessor (usable only if the object is a number)
    double& get<double>();                 // non-const accessor (usable only if the object is a number)

    bool is<std::string>() const;          // check if the object is a string
    const std::string& get<std::string>() const;
                                           // const accessor (usable only if the object is a string)
    std::string& get<std::string>();       // non-const accessor (usable only if the object is a string)

    bool is<array>() const;                // check if the object is an array
    const array& get<array>() const;       // const accessor (usable only if the object is an array)
    array& get<array>();                   // non-const accessor (usable only if the object is an array)

    bool is<object>() const;               // check if the object is an "object"
    const object& get<object>() const;     // const accessor (usable only if the object is an object)
    object& get<object>();                 // non-const accessor (usable only if the object is an array)

    bool evaluate_as_boolean() const;      // evaluates the object as a boolean

    std::string serialize() const;         // returns the object in JSON representation
    template void serialize(Iter os) const;
                                           // serializes the object in JSON representation through an output iterator

    std::string to_str() const;            // returns the object in string (for casual use)

  };

}

The code below parses a JSON string and prints the contents of the object.

picojson::value v;

// parse the input
std::cin >> v;
std::string err = picojson::get_last_error();
if (! err.empty()) {
  std::cerr << err << std::endl;
  exit(1);
}

// check if the type of the value is "object"
if (! v.is<picojson::object>()) {
  std::cerr << "JSON is not an object" << std::endl;
  exit(2);
}

// obtain a const reference to the map, and print the contents
const picojson::value::object& obj = v.get<picojson::object>();
for (picojson::value::object::const_iterator i = obj.begin();
     i != obj.end();
     ++i) {
  std::cout << i->first << ': ' << i->second.to_str() << std::endl;
}

Please note that the type check is mandatory; do not forget to check the type of the object by calling is<type>() before accessing the value by calling get<type>().

Reading JSON using the streaming (event-driven) interface

Please refer to the implementation of picojson::default_parse_context and picojson::null_parse_context. There is also an example (examples/streaming.cc) .

Serializing to JSON

Instances of the picojson::value class can be serialized in three ways, to ostream, to std::string, or to an output iterator.

picojson::value v;
...
std::cout << v;
picojson::value v;
...
std::string json = v.serialize();
picojson::value v;
...
v.serialize(std::ostream_iterator<char>(std::cout));

Experimental support for int64_t

Experimental suport for int64_t becomes available if the code is compiled with preprocessor macro PICOJSON_USE_INT64.

Turning on the feature will cause following changes to picojson:

  • new constructor picojson::value(int64_t) is defined
  • is<int64_t>() and get<int64_t>() become available
  • numerics in JSON within the bounds of int64_t and not using . nor e/E are considered as int64 type
  • the values are also avaliable as doubles as well (i.e. all values which are .is<int64_t>() == true are also .is<double>() == true)
  • int64 values are converted to double once get<double>() is called

Enabling the feature should not cause compatibility problem with code that do not use the feature.

Further reading

Examples can be found in the examples directory, and on the Wiki. Please add your favorite examples to the Wiki.

picojson's People

Contributors

amikhalev avatar bavay avatar billyoneal avatar fetus-hina avatar gabrielegiuseppini avatar gnaggnoyil avatar herumi avatar hirohitokato avatar jkeller-miovision avatar karya0 avatar kazuho avatar kzk avatar mattn avatar objectx avatar olafmandel avatar optiligence avatar over-the-stardust avatar rosset avatar satoren avatar sekogan avatar thalhammer avatar tolonuk avatar turenar avatar weirdgiraffe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

picojson's Issues

picojson - Abort on parsing possible DoS

During a security review of picojson i found an interesting testcase which will crash picojson due to an abort call, the issue seems to be related to how picojson handle numbers with exponent, below a screenshot:

schermata 2017-02-07 alle 01 50 23

i don't investigate further anyway would be nice to have this fixed, let me know if you need more info.

Best Regards,
Daniele

value::operator= does not allow for navigation

The current implementation of value::operator= first destroys the current value and then assigns the new value.

This breaks cases in which you want to descend iteratively down an object hiearchy, as in the following example:

for (auto k : paths) // paths is an iterator of keys
{
    if (branchV.is<picojson::null>()
        || !branchV.is<picojson::object>())
    {
        throw JSONFieldConversionException("JSON value is null or not an object");
    }

    const picojson::value::object & obj = branchV.get<picojson::object>();
    const auto & it = obj.find(k);
    if (it == obj.end())
    {
            throw JSONFieldConversionException("Cannot find element \"" + k + "\" in JSON object");
    }

    branchV = it->second; // this breaks
}

The last statement breaks because the assignment first destroys the current value, which ends up invalidating the iterator.

Hexadecimal support

JSON strings like:

{ "a": 0x123 } are not parsed correctly.

The patch fixing the issue is below

Why is there no `parse_object_stop` in the streaming API?

There is a parse_array_start / parse_array_stop matching pair, and it was almost trivial for me to add one for parse_object_stop. So why is it missing?

In fact, it simplified one of my parsers greatly, and it also matches the API of other parsers (as well as seeming like it belongs in the API here, too?)

I hope that by adding+using it I am not missing something... or that there is a more elegant way enabled by the library, where I shouldn't need to add it.

I should also note that this library seems to be unlike others in its class (streaming, callback-based parsers such as libjson, or json-streaming-parser), where the picojson callback API has the additional parse_object_item and parse_array_item functions which re-enter the parser. It actually made things easier, but it doesn't seem like other SAX parsers, so I'm worried about what the trade-offs or corner cases might be.

picojson eats one too many characters when parsing a number

Error: When the string begins with a number, parsing eats one too many characters.

Consider the string 2x. When picojson parses this it does:

Start reading number: Get 2, fine. Get x, end of number, call ungetc, return.
However, the character in the ungetc buffer gets dropped, and I have no way to access it. The return pointer points one past the x, so when I use to check if my whole buffer was parsed correctly, everything is fine.

picojson does not support -fno-exceptions

Repro

  1. Put file as foo.cc with below content
  2. Run clang++ -fno-exceptions foo.cc
#include "/path/to/picojson.h"
int main() { return 0; }
// foo.cc

Expected

It compiles successfully

Actual

Many compilation errors for example:

picojson.h:1142:3: error: cannot use 'throw' with exceptions disabled
  PICOJSON_ASSERT(0);
  ^

String to array

Hello, is there any way to convert string or char [] to an array of ASCII codes in JSON?
The only example with array that i found uses parse from "[1, true, \"text\"]" to create an array.

Something like this:

{
  "example_string": "abc",
  "example_array": [61, 62, 63]
}

Thanks!

Support arbitrary precision numbers

I would like to use picojson in a situation where the numbers are very large, and I use gmp.

I don't expect picojson to support gmp, instead I would like picojson to just provide hooks.

At the moment I have a version of picojson where at the top I have a block of code like:

#ifndef PICOJSON_REPLACE_DOUBLE
  typedef double JsonNumber;
  inline bool picoJson_isFinite(JsonNumber) { ... }
  inline std::string picoJson_DoubleToString(JsonNumber) { ... }
  inline double picoJson_StringToDouble(std::string) { ... } // this method can throw
#endif

Basically, providing a configuration point for all the places where doubles are currently manipulated, so a user can easily provide an alternative overload for these methods. Alternatively, these could be spread throughout the code?

I just was wondering if you would be interested in this code before I go to the effort of cleaning it up, or if I should just keep it as local changes.

This could be used to replace the int64_t code (at the cost of changing the interface which is currently being used -- instead we would provide a 'struct number { int64_t i; double d; bool is_double};' class and appropriate overloads).

Couldn't parse simply JSON string

I'm trying to parse a simple JSON string but value.is<picojson::object>() is false. Am I doing anything wrong? What's probably unique is that the outermost JSON is an array.

#include <iostream>
#include <string>
#include "../picojson.h"

using namespace std;

int main()
{

    const char* _json_resp = "[{\"id\": \"bitcoin\",\"name\": \"Bitcoin\",\"symbol\": \"BTC\",\"rank\": \"1\",\"price_usd\": \"1802.22\", \"price_btc\": \"1.0\",\"24h_volume_usd\": \"449860000.0\", \"market_cap_usd\": \"29430703155.0\", \"available_supply\": \"16330250.0\", \"total_supply\": \"16330250.0\", \"percent_change_1h\": \"0.5\", \"percent_change_24h\": \"1.32\", \"percent_change_7d\": \"14.22\", \"last_updated\": \"1494797050\"}]";

    picojson::value value;
    string err_msg = picojson::parse(value, _json_resp);
    if (!err_msg.empty()) {
      printf("can't parse JSON result: %s\n", err_msg.c_str());
    }

    if (!value.is<picojson::object>()) {
      printf("is not object\n"); // <-- errors
    }
}

Versioning and License file

Greetings!

I would like to create a simple rpm for Fedora channels, primarily for packages that would like to leverage, can just specify a dependency.

However the package is missing a couple of things:
1.) License File. I know it's BSD, but typically there is a separate LICENSE file to indicate.
2.) Version = ?
3.) Possible make 'check|test' target to ensure all is well

Let me know what your thoughts are and if you're too occupied I may just make a pull request.

new ( this ) value ( x ); won't compile on visual studio 2010

new ( this ) value ( x ); this line is causing me problems, i cannot replace in any way , is the picojson supposed to work only in c++11 ? i still have visual studio 2010 , and the compiler stops with a c2059 error ( invalid token ), how can i walk aorund this problem ?
thanks

do "explicit" is needed in the constructor ?

if exclude "explicit" from constructors,can write like below in C++11.

picojson::value a = picojson::array{3LL, "v", 3.0, 4.0, "test", false, true};

picojson::value o = picojson::object{ 
  { "a","value" },
  { "b",false },
  { "c",445.0 },
  { "d","text" },
  {"array", picojson::array{3LL, "v", 23.0, 4.0, "test", false, true} },
  {"child", picojson::object{{"key","value"}}},
  };

Consider removing static objects

Static objects (for example string returned by picojson::get_last_error) disqualify the library from multithreaded applications.

Maintaining order of values when serializing.

Would it be possible to add support to maintain the original order of json object value entries, as they were specified int he original json that was parsed, when serializing a json DOM?

I have json object values ordered to be more comprehensible when input into the parser, but when I serialize the same DOM they come out in lexicographic order. I know this has to do with using std maps as json objects, since traversing those with the map iterator will yield a sorting by key, but it may be possible.

consider exposing value::_type or provide a value::_type to std::string utility

I'm passing around some picojson objects/values and wanted to assert on type. As part of my message, I wanted to dump the type of value I got:

M_ASSERT_MSG(
    input.is<picojson::object>(),
     "Expecting a JSON object, got " << to_type_string(input)
);

As a workaround, I've written this in my code to do it:

std::string
to_type_string(const picojson::value & v)
{
    if(v.is<bool>()) return "bool";
    else
    if(v.is<picojson::null>()) return "null";
    else
    if(v.is<int64_t>()) return "int";
    else
    if(v.is<float64>()) return "float";
    else
    if(v.is<std::string>()) return "string";
    else
    if(v.is<picojson::array>()) return "array";
    else
    if(v.is<picojson::object>()) return "object";
    else
    if(v.is<picojson::object>()) return "object";
    return "unknown";
}

missed colon in the first example in readme

The first example from:

std::string json = "[ \"hello JSON\" ]";
picojson::value v;
std::string err = picojson::parse(v, json);
if (! err.empty()) {
  std:cerr << err << std::endl;
}

std:cerr should be std::cerr

bug on Solaris10 (gcc version 4.4.2)

Hello,

I tried to use picojson.h(version1.3.0) on Solaris 10 (gcc version 4.4.2)
And I got the following errors.

Is it possible to fix the bug on picojson.h?

---->
In file included from ./ms_conf.cpp:24:
./picojson.h: In constructor 'picojson::value::value(double)':
./picojson.h:200: error: 'isnan' is not a member of 'std'
./picojson.h:200: error: 'isinf' is not a member of 'std'
*** Error code 1
The following command caused the error:
<---

MSVC10: _isinf missing

Line 166 of picojson.h, MSVC10 doesn't seem to define _isinf. A possible fix is to use !_finite(n) instead. I suggest using this one as it seems to be defined by all major Visual Studio compiler versions.

Crashes parsing end of array or empty array

The following JSON causes the code below it to fail when it gets to the end of the array. Specifically, I get a bad_alloc exception (on OS X):

Podtique(44576,0x7fff7c44d300) malloc: *** mach_vm_map(size=107202383921152) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug

This happens on the line with " <===== bad_alloc" below.

[
    {
        "freq" : 0.1,
        "desc" : "Desc1",
        "playlist" :
        [
        ]
    }
]

[
    {
        "freq" : 0.1,
        "desc" : "Desc2",
        "playlist" :
        [
            "one",
            "two"
        ]
    }
]

bool
getFromJSONIter(picojson::value::array::const_iterator& inIter, const std::string& inKey, std::string& outVal)
{
    if (!inIter->is<picojson::value::object>())
    {
        return false;
    }

    picojson::value::object obj = inIter->get<picojson::value::object>();
    const picojson::value& v = obj[inKey];
    if (!v.is<std::string>())
    {
        return false;
    }
    outVal = v.get<std::string>();

    return true;
}

bool
getFromJSONIter(picojson::value::array::const_iterator& inIter, const std::string& inKey, double& outVal)
{
    if (!inIter->is<picojson::value::object>())
    {
        return false;
    }

    picojson::value::object obj = inIter->get<picojson::value::object>();
    const picojson::value& v = obj[inKey];
    if (!v.is<double>())
    {
        return false;
    }
    outVal = v.get<double>();

    return true;
}

bool
getFromJSONIter(picojson::value::array::const_iterator& inIter, const std::string& inKey, picojson::value::array& outVal)
{
    if (!inIter->is<picojson::value::object>())
    {
        return false;
    }

    picojson::value::object obj = inIter->get<picojson::value::object>();
    const picojson::value& v = obj[inKey];
    if (!v.is<picojson::value::array>())
    {
        return false;
    }
    outVal = v.get<picojson::value::array>();

    return true;
}

bool
Spectrum::parseSpectrum(const picojson::value& inJSON)
{
    //  Top level is an array…

    if (!inJSON.is<picojson::array>())
    {
        return false;
    }

    const picojson::value::array& stations = inJSON.get<picojson::array>();
    for (picojson::value::array::const_iterator iter = stations.begin(); iter != stations.end(); ++iter)
    {
        std::string desc;
        if (!getFromJSONIter(iter, "desc", desc)) { continue; }

        double freq;
        if (!getFromJSONIter(iter, "freq", freq)) { continue; }

        picojson::value::array playlist;
        if (!getFromJSONIter(iter, "playlist", playlist)) { continue; }

        LogDebug("Station: %s, freq: %f, tracks: %lu", desc.c_str(), freq, playlist.size());

        int i = 0;
        for (picojson::value::array::const_iterator trackIter = playlist.begin(); iter != playlist.end(); ++trackIter)
        {
            if (!trackIter->is<std::string>()) { continue; }
            std::string track = trackIter->get<std::string>();      <===== bad_alloc
            LogDebug("Track %02d: %s", i++, track.c_str());
        }


    }
    return true;
}

Warning about __STDC_FORMAT_MACROS

Hi!

I use picojson in my software.
Thank you for developing picojson!
Before including picojson.h, my software defines __STDC_FORMAT_MACROS and includes inttypes.h.
In this case, there is a warning about __STDC_FORMAT_MACROS.

picojson.h:71:10 warning: '__STDC_FORMAT_MACROS' macro redefined [-Wmacro-redefined]

To solve this problem, include guard is required as follows.

ifndef __STDC_FORMAT_MACROS

define __STDC_FORMAT_MACROS

endif

Please consider this revision.

No function to access nested values

There isn't a function to access nested values.
eg. This would not work

picojson::value v;
v = ...;
picojson::value child = v.get("hello.world.nested");

So you have to do this now

picojson::value v;
v = ...;
picojson::value child = v.get("hello").get("world").get("nested");

Which, is more messy, and also makes certain API's using this not very ergonomic.

Picojson has evil globals

Some features of picojson cannot be used from separate threads because last_error_t has a shared global variable in it without any concurrent access control.

Throw std::runtime_error instead of using assert()

Picojson uses assert() to detect usage errors and runtime errors. But they should better be changed to throwing std::runtime_error, since the latter would give applications a change to gracefully terminate the operation.

operator== does not honor int64_t

When comparing int64 values in operator==, they are first converted to double and then compared.
Thus 2 large integers (>52bits) that are different but similar will compare equal.

Sometimes picojson's .mkdn isn't easy to see.

Visual Studio Code(by default) can't recognition .mkdn file as markdown.

Please change the README's filename extention from .mkdn to .md .
You know, It's a VSCode's ploblem. But filename extention "md" is more popular than "mkdn", I think changeing filename extention is not bad idea.
Please fix the small ploblem to be better.

Add support for int64_t, as a subtype of double

Numbers should be parsed as both integers and floats, and if the result is within the bounds of int64_t, the value should be provided to the application via both of get<int64_t>() and get<double>().

By implementing support for integer type this way, we can support users looking for integer support (see #14) without breaking backward compatibility.

numeric limits min, max

In order to not add undef directive on windows projects, could be possibile to change std::numeric_limits<int64_t>::min() to (std::numeric_limits<int64_t>::min)() ?

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

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.)

parse sample with istream_iterator in README ignores whitespace in string

std::istream_iterator (actually, std::istream_iterator<char>) skips whitespace depending on the configuration of the underlying stream, and input streams are configured to skip whitespace by default.

So, the sample with std::istream_iterator in README ignores whitespace in string in JSON.

To fix this, std::noskipws manipulator should be applied to the stream, or the sample needs to use std::istreambuf_iterator<char> instead.

Warning about return from void function

Hi,
In all header files where I included picojson.h Eclipse is printing out a warning:

template void value::serialize(Iter oi, bool prettify) const {
return _serialize(oi, prettify ? 0 : -1);
}

has a "return" statement even if declared void...

No operator[] for const object

If I get a const reference to an object type, I can't use [] to get at its elements. I have to make a non-const copy.

clang compiler warning for value::to_str()

Thanks for a nice library. Of small note I get the following compiler warning using the clang compiler:

picojson.h:272:3: warning: control may reach end of non-void function [-Wreturn-type]

Although one is never supposed to reach there, "return std::string()" would suppress the warning.

Map of Maps is incorrectly parsed

When given original.txt to picojson and serialized to string again, and manually curated to easily see the problem, we obtain reserialized.txt, which lacks information of the original JSON.
This issue is not problem of the serialization, but the parsing, as the object lacks this information too.

original.txt
reserialized.txt

Weird issues when using custom parse contexts

Hi there,

I seem to be having some issues when trying to create parsing contexts and I was wondering what I might be missing.

This is my input data:

[
    {
        "entry": "blah"
    }, 
    {
        "nested": "{\"dict\": 1, \"some\": \"string\"}"
    }
]

I seem to get this error message when trying to parse it using a custom parsing context class, err is filled with:

syntax error at line 1 near: {

The class I'm using is pretty much copied from the streaming example:

class ParseCmdContext : public picojson::deny_parse_context
{
public:
    ParseCmdContext()
        : m_count(0)
    {}

    bool parse_array_start()
    {
        return true;
    }

    template <typename Iter>
    bool parse_array_item(picojson::input<Iter>& in, size_t)
    {
        picojson::value item;
        picojson::default_parse_context ctx(&item);
        if(!picojson::_parse(ctx, in))
            return false;
        if(!item.is<picojson::object>())
            return false;

        std::cout << item.serialize(false) << std::endl;
        m_count++;
        return true;
    }

    bool parse_array_stop(size_t)
    {
        return true;
    }

    inline uint32_t count()const { return m_count; }

private:
    uint32_t m_count;
};

void test(const std::string& str)
{
   ParseCmdContext ctx;
    std::string err;
    picojson::_parse(ctx, str.c_str(), str.c_str()+strlen(str.c_str()), &err);

    if(!err.empty())
    {
        //error is printed here <<<
        std::cerr <<"ParseCmdCtx "<< err << std::endl;
    }

     err.clear();
    picojson::value unused;
     picojson::default_parse_context ctx(&unused);
    picojson::_parse(ctx, str.c_str(), str.c_str()+strlen(str.c_str()), &err);

    if(!err.empty())
    {
        // but not here, this works! which suggests that I'm doing something wrong...
        std::cerr <<"default_parse_context "<< err << std::endl;
    }
}

I have tried making a "bypass" context that is literally a copy of default_parse_context with prints added and it seems to show the same error as the above one when called, strangely enough, the default_parse_context works fine again.

class ParseSceneContext
{
protected:
    picojson::value *out_;

public:
    ParseSceneContext(picojson::value *out)
        : out_(out)
    {}

    bool set_null() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
      *out_ = picojson::value();
      return true;
    }
    bool set_bool(bool b) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
      *out_ = picojson::value(b);
      return true;
    }
  #ifdef PICOJSON_USE_INT64
    bool set_int64(int64_t i) {
      *out_ = value(i);
      return true;
    }
  #endif
    bool set_number(double f) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
      *out_ = picojson::value(f);
      return true;
    }
    template <typename Iter>
    bool parse_string(picojson::input<Iter> &in) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
      *out_ = picojson::value(picojson::string_type, false);
      return picojson::_parse_string(out_->get<std::string>(), in);
    }
    bool parse_array_start() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
      *out_ = picojson::value(picojson::array_type, false);
      return true;
    }
    template <typename Iter>
    bool parse_array_item(picojson::input<Iter> &in, size_t) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
      picojson::array &a = out_->get<picojson::array>();
      a.push_back(picojson::value());
      ParseSceneContext ctx(&a.back());
      return picojson::_parse(ctx, in);
    }
    bool parse_array_stop(size_t) {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
      return true;
    }
    bool parse_object_start() {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
      *out_ = picojson::value(picojson::object_type, false);
      return true;
    }
    template <typename Iter>
    bool parse_object_item(picojson::input<Iter> &in, const std::string &key)
    {
        std::cout << __PRETTY_FUNCTION__ << std::endl;
        std::cout << key << std::endl;
      picojson::object &o = out_->get<picojson::object>();
      ParseSceneContext ctx(&o[key]);
      return picojson::_parse(ctx, in);
    }
};

What am I missing?

Another weird thing I find with the streaming example is that it shows that it inherits from picojson::deny_parse_context but none of its methods are ever declared as virtual.

Get root node?

Hello!

If there is a way to get the root array in this code?

{
  book = {
    author = "Me",
    title = "JSON"
  }
}

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.