Skip to content

Commit

Permalink
Ease-of-use improvements for JSON creation
Browse files Browse the repository at this point in the history
  • Loading branch information
gbittoun committed Nov 19, 2017
1 parent a944d59 commit 2372f9d
Show file tree
Hide file tree
Showing 2 changed files with 220 additions and 9 deletions.
147 changes: 147 additions & 0 deletions picojson.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ class value {
template <typename Iter> void serialize(Iter os, bool prettify = false) const;
std::string serialize(bool prettify = false) const;

int get_type() const;

private:
template <typename T> value(const T *); // intentionally defined to block implicit conversion of pointer to bool
template <typename Iter> static void _indent(Iter os, int indent);
Expand Down Expand Up @@ -634,6 +636,10 @@ inline std::string value::_serialize(int indent) const {
return s;
}

inline int value::get_type() const {
return type_;
}

template <typename Iter> class input {
protected:
Iter cur_, end_;
Expand Down Expand Up @@ -1129,6 +1135,147 @@ inline bool operator==(const value &x, const value &y) {
inline bool operator!=(const value &x, const value &y) {
return !(x == y);
}

class easyjson
{
public:

//Constructors

easyjson() :
internal_value(*new picojson::value()),
needsDelete(true) {
}

easyjson(picojson::value & v) :
internal_value(v),
needsDelete(false) {
}

easyjson(bool b):
internal_value(*new picojson::value(b)),
needsDelete(true) {
}

easyjson(const char * c):
internal_value(*new picojson::value(std::string(c))),
needsDelete(true) {
}

easyjson(const std::string & s):
internal_value(*new picojson::value(s)),
needsDelete(true) {
}

easyjson(int value):
internal_value(*new picojson::value(double(value))),
needsDelete(true) {
}

easyjson(double d):
internal_value(*new picojson::value(d)),
needsDelete(true) {
}

// Copy constructor

easyjson(const easyjson & other) :
internal_value(*new picojson::value(other.get_value())),
needsDelete(true) {
get_value() = other.get_value();
}

// picojson::value accessor

const value & get_value() const
{
return internal_value;
}

value & get_value()
{
return internal_value;
}


// Equality operators

easyjson & operator=(bool b) {
PICOJSON_ASSERT(get_value().get_type() == null_type || get_value().get_type() == boolean_type);
get_value() = picojson::value(b);
return *this;
}

easyjson & operator=(const char * c) {
PICOJSON_ASSERT(get_value().get_type() == null_type || get_value().get_type() == string_type);
get_value() = picojson::value(std::string(c));
return *this;
}

easyjson & operator=(const std::string & s) {
PICOJSON_ASSERT(get_value().get_type() == null_type || get_value().get_type() == string_type);
get_value() = picojson::value(s);
return *this;
}

easyjson & operator=(int i) {
PICOJSON_ASSERT(get_value().get_type() == null_type || get_value().get_type() == number_type);
get_value() = picojson::value(double(i));
return *this;
}

easyjson & operator=(double d) {
PICOJSON_ASSERT(get_value().get_type() == null_type || get_value().get_type() == number_type);
get_value() = picojson::value(d);
return *this;
}

easyjson & operator=(const easyjson & other) {
get_value() = other.get_value();
return *this;
}

// Assignment operators

easyjson operator[](const std::string & s) {
PICOJSON_ASSERT(get_value().get_type() == null_type || get_value().get_type() == object_type);

if (get_value().get_type() == null_type)
get_value().set<picojson::value::object>(picojson::value::object());

return get_value().get<picojson::value::object>()[std::string(s)];
}

easyjson operator[](const char * c) {
return operator[](std::string(c));
}

easyjson operator[](picojson::value::array::size_type index) {
PICOJSON_ASSERT(get_value().get_type() == null_type || get_value().get_type() == array_type);

if (get_value().get_type() == null_type) {
get_value().set<picojson::value::array>(picojson::value::array(index + 1));
}

if (get_value().get<picojson::value::array>().size() <= index) {
get_value().get<picojson::value::array>().resize(index + 1);
}

return get_value().get<picojson::value::array>().at(index);
}

~easyjson()
{
if (needsDelete)
{
delete &internal_value;
}
}
private:
picojson::value & internal_value;
bool needsDelete;
};

}

#if !PICOJSON_USE_RVALUE_REFERENCE
Expand Down
82 changes: 73 additions & 9 deletions test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ int main(void)
// constructors
#define TEST(expr, expected) \
is(picojson::value expr .serialize(), string(expected), "picojson::value" #expr)

TEST( (true), "true");
TEST( (false), "false");
TEST( (42.0), "42");
Expand All @@ -73,9 +73,9 @@ int main(void)
a *= 2;
}
}

#undef TEST

#define TEST(in, type, cmp, serialize_test) { \
picojson::value v; \
const char* s = in; \
Expand Down Expand Up @@ -116,7 +116,7 @@ int main(void)
TEST(array, "[]");
TEST(object, "{}");
#undef TEST

{
picojson::value v;
const char *s = "[1,true,\"hello\"]";
Expand All @@ -135,7 +135,7 @@ int main(void)
is(v.get(2).get<string>(), string("hello"), "check array[2] value");
_ok(!v.contains(3), "check not contains array[3]");
}

{
picojson::value v;
const char *s = "{ \"a\": true }";
Expand Down Expand Up @@ -173,7 +173,7 @@ int main(void)
TEST("\n\bbell", "2 near: bell");
TEST("\"abc\nd\"", "1 near: ");
#undef TEST

{
picojson::value v1, v2;
const char *s;
Expand Down Expand Up @@ -226,15 +226,15 @@ int main(void)

_ok(picojson::value(3.0).serialize() == "3",
"integral number should be serialized as a integer");

{
const char* s = "{ \"a\": [1,2], \"d\": 2 }";
picojson::null_parse_context ctx;
string err;
picojson::_parse(ctx, s, s + strlen(s), &err);
_ok(err.empty(), "null_parse_context");
}

{
picojson::value v1, v2;
v1 = picojson::value(true);
Expand All @@ -254,7 +254,7 @@ int main(void)
_ok(v1.is<picojson::array>(), "swap (array)");
_ok(v2.is<picojson::object>(), "swap (object)");
}

{
picojson::value v;
const char *s = "{ \"a\": 1, \"b\": [ 2, { \"b1\": \"abc\" } ], \"c\": {}, \"d\": [] }";
Expand Down Expand Up @@ -344,5 +344,69 @@ int main(void)
is(*reststr, 'a', "should point at the next char");
}

{
picojson::easyjson v("foo");
_ok(v.get_value().get<std::string>() == "foo", "equals value");
v = "bar";
_ok(v.get_value().get<std::string>() == "bar", "equals value");
}

{
picojson::easyjson v(std::string("foo"));
_ok(v.get_value().get<std::string>() == "foo", "equals value");
v = std::string("bar");
_ok(v.get_value().get<std::string>() == "bar", "equals value");
}

{
picojson::easyjson v(1);
_ok(v.get_value().get<double>() == 1, "equals value");
v = 2;
_ok(v.get_value().get<double>() == 2, "equals value");
}

{
picojson::easyjson v(1.0f);
_ok(v.get_value().get<double>() == 1.0f, "equals value");
v = 2.0f;
_ok(v.get_value().get<double>() == 2.0f, "equals value");
}

{
picojson::easyjson v(1.0);
_ok(v.get_value().get<double>() == 1.0, "equals value");
v = 2.0;
_ok(v.get_value().get<double>() == 2.0, "equals value");
}

{
picojson::easyjson v;
v["foo"] = 12;
_ok(v["foo"].get_value().get<double>() == 12, "equals value");
}

{
picojson::easyjson v;
v[12] = "foo";
_ok(v[12].get_value().get<std::string>() == "foo", "equals value");
}

{
picojson::easyjson v, v_equal;
v["foo"] = "bar";
v_equal = v;
picojson::easyjson v_copy(v);

_ok(v["foo"].get_value().get<std::string>() == v_copy["foo"].get_value().get<std::string>(), "copy equals original");
_ok(v["foo"].get_value().get<std::string>() == v_equal["foo"].get_value().get<std::string>(), "equality assigned to original");

v_copy["foo"] = "baz";
v_equal["foo"] = "picojson rocks !";

_ok(v["foo"].get_value().get<std::string>() == "bar", "original not modified");
_ok(v_copy["foo"].get_value().get<std::string>() == "baz", "changed value in copy is OK");
_ok(v_equal["foo"].get_value().get<std::string>() == "picojson rocks !", "changed value after equality is OK");
}

return done_testing();
}

0 comments on commit 2372f9d

Please sign in to comment.