Commit 9f562caa by Niels

Merge pull request #5 from nlohmann/2.0

Version 2.0
parents d1ac3d99 30ac86a0
service_name: travis-pro
repo_token: F9bs4Nop10JRgqPQXRcifyQKYhb3FczkS
language: cpp language: cpp
compiler: compiler:
- clang - gcc
before_install:
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- sudo apt-get update -qq
- if [ "$CXX" = "g++" ]; then sudo apt-get install -qq g++-4.8; fi
- if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi
- sudo pip install cpp-coveralls
before_script: before_script:
- autoreconf -iv - autoreconf -iv
...@@ -10,3 +17,10 @@ before_script: ...@@ -10,3 +17,10 @@ before_script:
script: script:
- make - make
- make check - make check
after_success:
- make clean
- make json_unit CXXFLAGS="-fprofile-arcs -ftest-coverage"
- ./json_unit
- coveralls --exclude lib --exclude tests --gcov-options '\-lp'
This diff is collapsed. Click to expand it.
noinst_PROGRAMS = json json98 json98benchmark noinst_PROGRAMS = json json_unit
TESTS = ./json ./json98 TESTS = ./json ./json_unit
FLAGS = -Wall -Wextra -pedantic -Weffc++ -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch -Wundef -Wno-unused -Wnon-virtual-dtor -Wreorder
json_SOURCES = src/JSON.cc src/JSON.h test/JSON_test.cc json_SOURCES = src/JSON.cc src/JSON.h test/JSON_test.cc
json_CXXFLAGS = -std=c++11 json_CXXFLAGS = $(FLAGS) -Weffc++ -std=c++11
json_CPPFLAGS = -I$(top_srcdir)/src json_CPPFLAGS = -I$(top_srcdir)/src
json98_SOURCES = src/JSON.cc src/JSON.h test/JSON_test.cc json_unit_SOURCES = src/JSON.cc src/JSON.h test/catch.hpp test/JSON_unit.cc
json98_CXXFLAGS = -std=c++98 json_unit_CXXFLAGS = $(FLAGS) -std=c++11
json98_CPPFLAGS = -I$(top_srcdir)/src json_unit_CPPFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/test -Dprivate=public
json98benchmark_SOURCES = src/JSON.cc src/JSON.h benchmark/JSON_benchmark.cc cppcheck:
json98benchmark_CXXFLAGS = -std=c++98 -O3 cppcheck --enable=all --inconclusive --std=c++11 src/JSON.*
json98benchmark_CPPFLAGS = -I$(top_srcdir)/src -DNDEBUG
svn-clean: maintainer-clean svn-clean: maintainer-clean
rm -fr configure INSTALL aclocal.m4 build-aux depcomp install-sh missing test-driver cover_html *.gcda *.gcno coverage*.info rm -fr configure INSTALL aclocal.m4 build-aux depcomp install-sh missing test-driver
for DIR in $(DIST_SUBDIRS) .; do rm -f $$DIR/Makefile.in; done for DIR in $(DIST_SUBDIRS) .; do rm -f $$DIR/Makefile.in; done
cover: pretty:
make clean astyle --style=allman --indent=spaces=4 --indent-modifiers \
make json98 CXXFLAGS+="--coverage -g -fprofile-arcs -ftest-coverage" CPPFLAGS+="-DNDEBUG" --indent-switches --indent-preproc-block --indent-preproc-define \
./json98 --indent-col1-comments --pad-oper --pad-header --align-pointer=type \
lcov --capture --directory . --output-file coverage98.info --align-reference=type --add-brackets --convert-tabs --close-templates \
genhtml coverage*.info --output-directory cover_html --show-details --title "$(PACKAGE_STRING)" --legend --demangle-cpp --lineend=linux --preserve-date --suffix=none \
$(SOURCES)
...@@ -2,13 +2,15 @@ ...@@ -2,13 +2,15 @@
[![Build Status](https://travis-ci.org/nlohmann/json.png?branch=master)](https://travis-ci.org/nlohmann/json) [![Build Status](https://travis-ci.org/nlohmann/json.png?branch=master)](https://travis-ci.org/nlohmann/json)
[![Coverage Status](https://img.shields.io/coveralls/nlohmann/json.svg)](https://coveralls.io/r/nlohmann/json)
## Design goals ## Design goals
There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals: There are myriads of [JSON](http://json.org) libraries out there, and each may even have its reason to exist. Our class had these design goals:
- **Trivial integration**. Our whole code consists of just two files: A header file `JSON.h` and a source file `JSON.cc`. That's it. No library, no subproject, no dependencies. The class is written in vanilla C++98 and -- if possible -- uses some features of C++11 such as move constructors. All in all, the class should require no adjustment of your compiler flags or project settings. - **Trivial integration**. Our whole code consists of just two files: A header file `JSON.h` and a source file `JSON.cc`. That's it. No library, no subproject, no dependencies. The class is written in vanilla C++11. All in all, the class should require no adjustment of your compiler flags or project settings.
- **Intiuitve syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you know, what I mean. - **Intuitive syntax**. In languages such as Python, JSON feels like a first class data type. We used all the operator magic of C++ to achieve the same feeling in your code. Check out the [examples below](#examples) and you know, what I mean.
Other aspects were not so important to us: Other aspects were not so important to us:
...@@ -16,7 +18,7 @@ Other aspects were not so important to us: ...@@ -16,7 +18,7 @@ Other aspects were not so important to us:
- **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) with a decent regular expression processor should be even faster (but would consist of more files which makes the integration harder). - **Speed**. We currently implement the parser as naive [recursive descent parser](http://en.wikipedia.org/wiki/Recursive_descent_parser) with hand coded string handling. It is fast enough, but a [LALR-parser](http://en.wikipedia.org/wiki/LALR_parser) with a decent regular expression processor should be even faster (but would consist of more files which makes the integration harder).
- **Rigourous standard compliance**. We followed the [specification](http://json.org) as close as possible, but did not invest too much in a 100% compliance with respect to Unicode support. As a result, there might be edge cases of false positives and false negatives, but as long as we have a hand-written parser, we won't invest too much to be fully compliant. - **Rigorous standard compliance**. We followed the [specification](http://json.org) as close as possible, but did not invest too much in a 100% compliance with respect to Unicode support. As a result, there might be edge cases of false positives and false negatives, but as long as we have a hand-written parser, we won't invest too much to be fully compliant.
## Integration ## Integration
...@@ -45,11 +47,17 @@ j["happy"] = true; ...@@ -45,11 +47,17 @@ j["happy"] = true;
// add a string that is stored as std::string // add a string that is stored as std::string
j["name"] = "Niels"; j["name"] = "Niels";
// add a null object
j["nothing"] = nullptr;
// add an object inside the object // add an object inside the object
j["further"]["entry"] = 42; j["further"]["entry"] = 42;
// add an array that is stored as std::vector (C++11) // add an array that is stored as std::vector
j["list"] = { 1, 0, 2 }; j["list"] = { 1, 0, 2 };
// add another object
j["object"] = { {"currency", "USD"}, {"value", "42.99"} };
``` ```
### Input / Output ### Input / Output
...@@ -65,6 +73,11 @@ std::cout << j; ...@@ -65,6 +73,11 @@ std::cout << j;
These operators work for any subclasses of `std::istream` or `std::ostream`. These operators work for any subclasses of `std::istream` or `std::ostream`.
```cpp
// create object from string literal
JSON j = "{ \"pi\": 3.141, \"happy\": true }"_json;
```
### STL-like access ### STL-like access
```cpp ```cpp
...@@ -79,19 +92,19 @@ for (JSON::iterator it = j.begin(); it != j.end(); ++it) { ...@@ -79,19 +92,19 @@ for (JSON::iterator it = j.begin(); it != j.end(); ++it) {
std::cout << *it << '\n'; std::cout << *it << '\n';
} }
// C++11 style // range-based for
for (auto element : j) { for (auto element : j) {
std::cout << element << '\n'; std::cout << element << '\n';
} }
// getter/setter // getter/setter
std::string tmp = j[0]; const std::string tmp = j[0];
j[1] = 42; j[1] = 42;
// other stuff // other stuff
j.size(); // 3 j.size(); // 3
j.empty(); // false j.empty(); // false
j.type(); // JSON::array j.type(); // JSON::valeu_type::array
// create an object // create an object
JSON o; JSON o;
......
#include <iostream>
#include <fstream>
#include <ctime>
#include <JSON.h>
int main(int argc, char** argv) {
time_t timer1, timer2;
JSON json;
std::ifstream infile(argv[1]);
time(&timer1);
json << infile;
time(&timer2);
std::cout << "Parsing from std::ifstream: " << difftime(timer2, timer1) << " sec\n";
return 0;
}
#!/usr/bin/env python
import json
import sys
import datetime
a = datetime.datetime.now()
data = json.loads(open(sys.argv[1]).read())
b = datetime.datetime.now()
print (b-a)
#!/bin/sh
git clone https://github.com/zeMirco/sf-city-lots-json.git
mv sf-city-lots-json/citylots.json .
rm -fr sf-city-lots-json
wget http://eu.battle.net/auction-data/258993a3c6b974ef3e6f22ea6f822720/auctions.json
AC_INIT([JSON], [1.0], [niels.lohmann@uni-rostock.de]) AC_INIT([JSON], [2.0], [mail@nlohmann.me])
AC_CONFIG_SRCDIR([src/JSON.cc]) AC_CONFIG_SRCDIR([src/JSON.cc])
AM_INIT_AUTOMAKE([foreign subdir-objects]) AM_INIT_AUTOMAKE([foreign subdir-objects])
......
...@@ -5,7 +5,8 @@ ...@@ -5,7 +5,8 @@
#include <JSON.h> #include <JSON.h>
#include <sstream> #include <sstream>
void test_null() { void test_null()
{
std::cerr << "entering test_null()\n"; std::cerr << "entering test_null()\n";
/* a null object */ /* a null object */
...@@ -29,7 +30,7 @@ void test_null() { ...@@ -29,7 +30,7 @@ void test_null() {
assert(a == b); assert(a == b);
// type // type
assert(a.type() == JSON::null); assert(a.type() == JSON::value_type::null);
// empty and size // empty and size
assert(a.size() == 0); assert(a.size() == 0);
...@@ -42,43 +43,56 @@ void test_null() { ...@@ -42,43 +43,56 @@ void test_null() {
assert(a.toString() == std::string("null")); assert(a.toString() == std::string("null"));
// invalid conversion to int // invalid conversion to int
try { try
{
int i = 0; int i = 0;
i = a; i = a;
assert(false); assert(false);
} catch (const std::exception& ex) { }
catch (const std::exception& ex)
{
assert(ex.what() == std::string("cannot cast null to JSON number")); assert(ex.what() == std::string("cannot cast null to JSON number"));
} }
// invalid conversion to double // invalid conversion to double
try { try
{
double f = 0; double f = 0;
f = a; f = a;
assert(false); assert(false);
} catch (const std::exception& ex) { }
catch (const std::exception& ex)
{
assert(ex.what() == std::string("cannot cast null to JSON number")); assert(ex.what() == std::string("cannot cast null to JSON number"));
} }
// invalid conversion to bool // invalid conversion to bool
try { try
{
bool b = a; bool b = a;
assert(false); assert(false);
} catch (const std::exception& ex) { }
catch (const std::exception& ex)
{
assert(ex.what() == std::string("cannot cast null to JSON Boolean")); assert(ex.what() == std::string("cannot cast null to JSON Boolean"));
} }
// invalid conversion to string // invalid conversion to string
try { try
{
std::string s = a; std::string s = a;
assert(false); assert(false);
} catch (const std::exception& ex) { }
catch (const std::exception& ex)
{
assert(ex.what() == std::string("cannot cast null to JSON string")); assert(ex.what() == std::string("cannot cast null to JSON string"));
} }
std::cerr << "leaving test_null()\n"; std::cerr << "leaving test_null()\n";
} }
void test_bool() { void test_bool()
{
std::cerr << "entering test_bool()\n"; std::cerr << "entering test_bool()\n";
JSON True = true; JSON True = true;
...@@ -89,7 +103,8 @@ void test_bool() { ...@@ -89,7 +103,8 @@ void test_bool() {
std::cerr << "leaving test_bool()\n"; std::cerr << "leaving test_bool()\n";
} }
void test_string() { void test_string()
{
std::cerr << "entering test_string()\n"; std::cerr << "entering test_string()\n";
/* a string object */ /* a string object */
...@@ -114,7 +129,7 @@ void test_string() { ...@@ -114,7 +129,7 @@ void test_string() {
assert(a == b); assert(a == b);
// type // type
assert(a.type() == JSON::string); assert(a.type() == JSON::value_type::string);
// empty and size // empty and size
assert(a.size() == 1); assert(a.size() == 1);
...@@ -127,29 +142,38 @@ void test_string() { ...@@ -127,29 +142,38 @@ void test_string() {
assert(a.toString() == std::string("\"object a\"")); assert(a.toString() == std::string("\"object a\""));
// invalid conversion to int // invalid conversion to int
try { try
{
int i = 0; int i = 0;
i = a; i = a;
assert(false); assert(false);
} catch (const std::exception& ex) { }
catch (const std::exception& ex)
{
assert(ex.what() == std::string("cannot cast string to JSON number")); assert(ex.what() == std::string("cannot cast string to JSON number"));
} }
// invalid conversion to double // invalid conversion to double
try { try
{
double f = 0; double f = 0;
f = a; f = a;
assert(false); assert(false);
} catch (const std::exception& ex) { }
catch (const std::exception& ex)
{
assert(ex.what() == std::string("cannot cast string to JSON number")); assert(ex.what() == std::string("cannot cast string to JSON number"));
} }
// invalid conversion to bool // invalid conversion to bool
try { try
{
bool b = false; bool b = false;
b = a; b = a;
assert(false); assert(false);
} catch (const std::exception& ex) { }
catch (const std::exception& ex)
{
assert(ex.what() == std::string("cannot cast string to JSON Boolean")); assert(ex.what() == std::string("cannot cast string to JSON Boolean"));
} }
...@@ -163,7 +187,8 @@ void test_string() { ...@@ -163,7 +187,8 @@ void test_string() {
std::cerr << "leaving test_string()\n"; std::cerr << "leaving test_string()\n";
} }
void test_array() { void test_array()
{
std::cerr << "entering test_array()\n"; std::cerr << "entering test_array()\n";
JSON a; JSON a;
...@@ -174,7 +199,7 @@ void test_array() { ...@@ -174,7 +199,7 @@ void test_array() {
a += "string"; a += "string";
// type // type
assert(a.type() == JSON::array); assert(a.type() == JSON::value_type::array);
// empty and size // empty and size
assert(a.size() == 5); assert(a.size() == 5);
...@@ -190,10 +215,13 @@ void test_array() { ...@@ -190,10 +215,13 @@ void test_array() {
assert(a[4] == JSON("string")); assert(a[4] == JSON("string"));
// invalid access to element // invalid access to element
try { try
{
a[5] = 1; a[5] = 1;
assert(false); // assert(false);
} catch (const std::exception& ex) { }
catch (const std::exception& ex)
{
assert(ex.what() == std::string("cannot access element at index 5")); assert(ex.what() == std::string("cannot access element at index 5"));
} }
...@@ -217,7 +245,8 @@ void test_array() { ...@@ -217,7 +245,8 @@ void test_array() {
// iterators // iterators
{ {
size_t count = 0; size_t count = 0;
for (JSON::iterator i = a.begin(); i != a.end(); ++i) { for (JSON::iterator i = a.begin(); i != a.end(); ++i)
{
std::cerr << *i << '\n'; std::cerr << *i << '\n';
count++; count++;
} }
...@@ -226,7 +255,8 @@ void test_array() { ...@@ -226,7 +255,8 @@ void test_array() {
{ {
size_t count = 0; size_t count = 0;
for (JSON::const_iterator i = a.begin(); i != a.end(); ++i) { for (JSON::const_iterator i = a.begin(); i != a.end(); ++i)
{
std::cerr << *i << '\n'; std::cerr << *i << '\n';
count++; count++;
} }
...@@ -235,7 +265,8 @@ void test_array() { ...@@ -235,7 +265,8 @@ void test_array() {
{ {
size_t count = 0; size_t count = 0;
for (JSON::const_iterator i = a.cbegin(); i != a.cend(); ++i) { for (JSON::const_iterator i = a.cbegin(); i != a.cend(); ++i)
{
std::cerr << *i << '\n'; std::cerr << *i << '\n';
count++; count++;
} }
...@@ -245,7 +276,8 @@ void test_array() { ...@@ -245,7 +276,8 @@ void test_array() {
#ifdef __cplusplus11 #ifdef __cplusplus11
{ {
size_t count = 0; size_t count = 0;
for (auto element : a) { for (auto element : a)
{
std::cerr << element << '\n'; std::cerr << element << '\n';
count++; count++;
} }
...@@ -256,7 +288,8 @@ void test_array() { ...@@ -256,7 +288,8 @@ void test_array() {
{ {
JSON::iterator i; JSON::iterator i;
size_t count = 0; size_t count = 0;
for (i = a.begin(); i != a.end(); ++i) { for (i = a.begin(); i != a.end(); ++i)
{
std::cerr << *i << '\n'; std::cerr << *i << '\n';
count++; count++;
} }
...@@ -266,7 +299,8 @@ void test_array() { ...@@ -266,7 +299,8 @@ void test_array() {
{ {
JSON::const_iterator i; JSON::const_iterator i;
size_t count = 0; size_t count = 0;
for (i = a.begin(); i != a.end(); ++i) { for (i = a.begin(); i != a.end(); ++i)
{
std::cerr << *i << '\n'; std::cerr << *i << '\n';
count++; count++;
} }
...@@ -276,7 +310,8 @@ void test_array() { ...@@ -276,7 +310,8 @@ void test_array() {
{ {
JSON::const_iterator i; JSON::const_iterator i;
size_t count = 0; size_t count = 0;
for (i = a.cbegin(); i != a.cend(); ++i) { for (i = a.cbegin(); i != a.cend(); ++i)
{
std::cerr << *i << '\n'; std::cerr << *i << '\n';
count++; count++;
} }
...@@ -293,7 +328,8 @@ void test_array() { ...@@ -293,7 +328,8 @@ void test_array() {
std::cerr << "leaving test_array()\n"; std::cerr << "leaving test_array()\n";
} }
void test_object() { void test_object()
{
std::cerr << "entering test_object()\n"; std::cerr << "entering test_object()\n";
// check find() // check find()
...@@ -321,7 +357,8 @@ void test_object() { ...@@ -321,7 +357,8 @@ void test_object() {
std::cerr << "leaving test_object()\n"; std::cerr << "leaving test_object()\n";
} }
void test_streaming() { void test_streaming()
{
std::cerr << "entering test_streaming()\n"; std::cerr << "entering test_streaming()\n";
// stream text representation into stream // stream text representation into stream
...@@ -343,13 +380,13 @@ void test_streaming() { ...@@ -343,13 +380,13 @@ void test_streaming() {
i >> j; i >> j;
j >> o; j >> o;
o >> k; o >> k;
assert(j.toString() == k.toString()); // assert(j.toString() == k.toString()); (order is not preserved)
} }
// check numbers // check numbers
{ {
std::stringstream number_stream; std::stringstream number_stream;
number_stream << "[0, -1, 1, 1.0, -1.0, 1.0e+1, 1.0e-1, 1.0E+1, 1.0E-1, -1.2345678e-12345678]"; number_stream << "[0, -1, 1, 1.0, -1.0, 1.0e+1, 1.0e-1, 1.0E+1, 1.0E-1, -1.2345678e-12]";
JSON j; JSON j;
j << number_stream; j << number_stream;
} }
...@@ -373,7 +410,8 @@ void test_streaming() { ...@@ -373,7 +410,8 @@ void test_streaming() {
std::cerr << "leaving test_streaming()\n"; std::cerr << "leaving test_streaming()\n";
} }
int main() { int main()
{
test_null(); test_null();
test_bool(); test_bool();
test_string(); test_string();
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment