Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
J
json
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
json
Commits
bd9f49ef
Commit
bd9f49ef
authored
Jan 06, 2015
by
Niels
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
implemented pretty printing (issue #13)
- to_string() method is now called dump() - syntax borrowed from Python’s json.dumps()
parent
08456b8f
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
126 additions
and
28 deletions
+126
-28
README.md
README.md
+11
-4
json.cc
src/json.cc
+85
-9
json.h
src/json.h
+11
-8
json_unit.cc
test/json_unit.cc
+19
-7
No files found.
README.md
View file @
bd9f49ef
...
@@ -112,13 +112,13 @@ You can create an object (deserialization) by appending `_json` to a string lite
...
@@ -112,13 +112,13 @@ You can create an object (deserialization) by appending `_json` to a string lite
```
cpp
```
cpp
// create object from string literal
// create object from string literal
json
j
=
"{
\"
pi
\"
: 3.141,
\"
happy
\"
: true
}"
_json
;
json
j
=
"{
\"
happy
\"
: true,
\"
pi
\"
: 3.141
}"
_json
;
// or even nicer (thanks http://isocpp.org/blog/2015/01/json-for-modern-cpp)
// or even nicer (thanks http://isocpp.org/blog/2015/01/json-for-modern-cpp)
auto
j2
=
R"(
auto
j2
=
R"(
{
{
"
pi": 3.141
,
"
happy": true
,
"
happy": true
"
pi": 3.141
})"
_json
;
})"
_json
;
```
```
...
@@ -126,7 +126,14 @@ You can also get a string representation (serialize):
...
@@ -126,7 +126,14 @@ You can also get a string representation (serialize):
```
cpp
```
cpp
// explicit conversion to string
// explicit conversion to string
std
::
string
s
=
j
.
to_string
();
std
::
string
s
=
j
.
dump
();
// {\"happy\": true, \"pi\": 3.141}
// serialization with pretty printing
std
::
cout
<<
j
.
dump
(
4
)
<<
std
::
endl
;
// {
// "happy": true,
// "pi": 3.141
// }
```
```
The value of s could be
`{"pi": 3.141, "happy": true}`
, but the order of the entries in the object is not fixed.
The value of s could be
`{"pi": 3.141, "happy": true}`
, but the order of the entries in the object is not fixed.
...
...
src/json.cc
View file @
bd9f49ef
...
@@ -472,8 +472,22 @@ json::operator object_t() const
...
@@ -472,8 +472,22 @@ json::operator object_t() const
return
get
<
object_t
>
();
return
get
<
object_t
>
();
}
}
const
std
::
string
json
::
to_string
()
const
noexcept
/*!
Internal implementation of the serialization function.
\param prettyPrint whether the output shall be pretty-printed
\param indentStep the indent level
\param currentIndent the current indent level (only used internally)
*/
const
std
::
string
json
::
dump
(
const
bool
prettyPrint
,
const
unsigned
int
indentStep
,
unsigned
int
currentIndent
)
const
noexcept
{
{
// helper function to return whitespace as indentation
const
auto
indent
=
[
prettyPrint
,
&
currentIndent
]()
{
return
prettyPrint
?
std
::
string
(
currentIndent
,
' '
)
:
std
::
string
();
};
switch
(
type_
)
switch
(
type_
)
{
{
case
(
value_type
:
:
string
)
:
case
(
value_type
:
:
string
)
:
...
@@ -498,34 +512,73 @@ const std::string json::to_string() const noexcept
...
@@ -498,34 +512,73 @@ const std::string json::to_string() const noexcept
case
(
value_type
:
:
array
)
:
case
(
value_type
:
:
array
)
:
{
{
std
::
string
result
;
if
(
value_
.
array
->
empty
())
{
return
"[]"
;
}
std
::
string
result
=
"["
;
// increase indentation
if
(
prettyPrint
)
{
currentIndent
+=
indentStep
;
result
+=
"
\n
"
;
}
for
(
array_t
::
const_iterator
i
=
value_
.
array
->
begin
();
i
!=
value_
.
array
->
end
();
++
i
)
for
(
array_t
::
const_iterator
i
=
value_
.
array
->
begin
();
i
!=
value_
.
array
->
end
();
++
i
)
{
{
if
(
i
!=
value_
.
array
->
begin
())
if
(
i
!=
value_
.
array
->
begin
())
{
{
result
+=
", "
;
result
+=
prettyPrint
?
",
\n
"
:
", "
;
}
}
result
+=
i
->
to_string
();
result
+=
indent
()
+
i
->
dump
(
prettyPrint
,
indentStep
,
currentIndent
);
}
// decrease indentation
if
(
prettyPrint
)
{
currentIndent
-=
indentStep
;
result
+=
"
\n
"
;
}
}
return
"["
+
result
+
"]"
;
return
result
+
indent
()
+
"]"
;
}
}
case
(
value_type
:
:
object
)
:
case
(
value_type
:
:
object
)
:
{
{
std
::
string
result
;
if
(
value_
.
object
->
empty
())
{
return
"{}"
;
}
std
::
string
result
=
"{"
;
// increase indentation
if
(
prettyPrint
)
{
currentIndent
+=
indentStep
;
result
+=
"
\n
"
;
}
for
(
object_t
::
const_iterator
i
=
value_
.
object
->
begin
();
i
!=
value_
.
object
->
end
();
++
i
)
for
(
object_t
::
const_iterator
i
=
value_
.
object
->
begin
();
i
!=
value_
.
object
->
end
();
++
i
)
{
{
if
(
i
!=
value_
.
object
->
begin
())
if
(
i
!=
value_
.
object
->
begin
())
{
{
result
+=
", "
;
result
+=
prettyPrint
?
",
\n
"
:
", "
;
}
}
result
+=
"
\"
"
+
i
->
first
+
"
\"
: "
+
i
->
second
.
to_string
();
result
+=
indent
()
+
"
\"
"
+
i
->
first
+
"
\"
: "
+
i
->
second
.
dump
(
prettyPrint
,
indentStep
,
currentIndent
);
}
// decrease indentation
if
(
prettyPrint
)
{
currentIndent
-=
indentStep
;
result
+=
"
\n
"
;
}
}
return
"{"
+
result
+
"}"
;
return
result
+
indent
()
+
"}"
;
}
}
// actually only value_type::null - but making the compiler happy
// actually only value_type::null - but making the compiler happy
...
@@ -536,6 +589,29 @@ const std::string json::to_string() const noexcept
...
@@ -536,6 +589,29 @@ const std::string json::to_string() const noexcept
}
}
}
}
/*!
Serialization function for JSON objects. The function tries to mimick Python's
\p json.dumps() function, and currently supports its \p indent parameter.
\param indent if indent is nonnegative, then array elements and object members
will be pretty-printed with that indent level. An indent level
of 0 will only insert newlines. -1 (the default) selects the
most compact representation
\see https://docs.python.org/2/library/json.html#json.dump
*/
const
std
::
string
json
::
dump
(
int
indent
)
const
noexcept
{
if
(
indent
>=
0
)
{
return
dump
(
true
,
static_cast
<
unsigned
int
>
(
indent
));
}
else
{
return
dump
(
false
,
0
);
}
}
///////////////////////////////////////////
///////////////////////////////////////////
// ADDING ELEMENTS TO OBJECTS AND ARRAYS //
// ADDING ELEMENTS TO OBJECTS AND ARRAYS //
...
...
src/json.h
View file @
bd9f49ef
...
@@ -162,6 +162,9 @@ class json
...
@@ -162,6 +162,9 @@ class json
/// return the type as string
/// return the type as string
const
std
::
string
type_name
()
const
noexcept
;
const
std
::
string
type_name
()
const
noexcept
;
/// dump the object (with pretty printer)
const
std
::
string
dump
(
const
bool
,
const
unsigned
int
,
unsigned
int
=
0
)
const
noexcept
;
public
:
public
:
/// explicit value conversion
/// explicit value conversion
template
<
typename
T
>
template
<
typename
T
>
...
@@ -180,34 +183,34 @@ class json
...
@@ -180,34 +183,34 @@ class json
/// implicit conversion to JSON map (only for objects)
/// implicit conversion to JSON map (only for objects)
operator
object_t
()
const
;
operator
object_t
()
const
;
///
writ
e to stream
///
serializ
e to stream
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
o
,
const
json
&
j
)
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
o
,
const
json
&
j
)
{
{
o
<<
j
.
to_string
();
o
<<
j
.
dump
();
return
o
;
return
o
;
}
}
///
writ
e to stream
///
serializ
e to stream
friend
std
::
ostream
&
operator
>>
(
const
json
&
j
,
std
::
ostream
&
o
)
friend
std
::
ostream
&
operator
>>
(
const
json
&
j
,
std
::
ostream
&
o
)
{
{
o
<<
j
.
to_string
();
o
<<
j
.
dump
();
return
o
;
return
o
;
}
}
///
read
from stream
///
deserialize
from stream
friend
std
::
istream
&
operator
>>
(
std
::
istream
&
i
,
json
&
j
)
friend
std
::
istream
&
operator
>>
(
std
::
istream
&
i
,
json
&
j
)
{
{
j
=
parser
(
i
).
parse
();
j
=
parser
(
i
).
parse
();
return
i
;
return
i
;
}
}
///
read
from stream
///
deserialize
from stream
friend
std
::
istream
&
operator
<<
(
json
&
j
,
std
::
istream
&
i
)
friend
std
::
istream
&
operator
<<
(
json
&
j
,
std
::
istream
&
i
)
{
{
j
=
parser
(
i
).
parse
();
j
=
parser
(
i
).
parse
();
return
i
;
return
i
;
}
}
/// explicit
conversion to string representation (C++ style)
/// explicit
serialization
const
std
::
string
to_string
(
)
const
noexcept
;
const
std
::
string
dump
(
int
=
-
1
)
const
noexcept
;
/// add an object/array to an array
/// add an object/array to an array
json
&
operator
+=
(
const
json
&
);
json
&
operator
+=
(
const
json
&
);
...
...
test/json_unit.cc
View file @
bd9f49ef
...
@@ -17,7 +17,7 @@ TEST_CASE("array")
...
@@ -17,7 +17,7 @@ TEST_CASE("array")
const
json
j_const
(
j
);
const
json
j_const
(
j
);
// string representation of default value
// string representation of default value
CHECK
(
j
.
to_string
()
==
"[]"
);
CHECK
(
j
.
dump
()
==
"[]"
);
// iterators
// iterators
CHECK
(
j
.
begin
()
!=
j
.
end
());
CHECK
(
j
.
begin
()
!=
j
.
end
());
...
@@ -305,7 +305,7 @@ TEST_CASE("object")
...
@@ -305,7 +305,7 @@ TEST_CASE("object")
const
json
j_const
=
j
;
const
json
j_const
=
j
;
// string representation of default value
// string representation of default value
CHECK
(
j
.
to_string
()
==
"{}"
);
CHECK
(
j
.
dump
()
==
"{}"
);
// iterators
// iterators
CHECK
(
j
.
begin
()
!=
j
.
end
());
CHECK
(
j
.
begin
()
!=
j
.
end
());
...
@@ -685,7 +685,7 @@ TEST_CASE("null")
...
@@ -685,7 +685,7 @@ TEST_CASE("null")
CHECK
(
j
.
type
()
==
json
::
value_type
::
null
);
CHECK
(
j
.
type
()
==
json
::
value_type
::
null
);
// string representation of default value
// string representation of default value
CHECK
(
j
.
to_string
()
==
"null"
);
CHECK
(
j
.
dump
()
==
"null"
);
// iterators
// iterators
CHECK
(
j
.
begin
()
!=
j
.
end
());
CHECK
(
j
.
begin
()
!=
j
.
end
());
...
@@ -755,7 +755,7 @@ TEST_CASE("string")
...
@@ -755,7 +755,7 @@ TEST_CASE("string")
CHECK
(
j
.
cbegin
()
!=
j
.
cend
());
CHECK
(
j
.
cbegin
()
!=
j
.
cend
());
// string representation of default value
// string representation of default value
CHECK
(
j
.
to_string
()
==
"
\"\"
"
);
CHECK
(
j
.
dump
()
==
"
\"\"
"
);
// container members
// container members
CHECK
(
j
.
size
()
==
1
);
CHECK
(
j
.
size
()
==
1
);
...
@@ -837,7 +837,7 @@ TEST_CASE("boolean")
...
@@ -837,7 +837,7 @@ TEST_CASE("boolean")
CHECK
(
j
.
cbegin
()
!=
j
.
cend
());
CHECK
(
j
.
cbegin
()
!=
j
.
cend
());
// string representation of default value
// string representation of default value
CHECK
(
j
.
to_string
()
==
"false"
);
CHECK
(
j
.
dump
()
==
"false"
);
// container members
// container members
CHECK
(
j
.
size
()
==
1
);
CHECK
(
j
.
size
()
==
1
);
...
@@ -916,7 +916,7 @@ TEST_CASE("number (int)")
...
@@ -916,7 +916,7 @@ TEST_CASE("number (int)")
CHECK
(
j
.
cbegin
()
!=
j
.
cend
());
CHECK
(
j
.
cbegin
()
!=
j
.
cend
());
// string representation of default value
// string representation of default value
CHECK
(
j
.
to_string
()
==
"0"
);
CHECK
(
j
.
dump
()
==
"0"
);
// container members
// container members
CHECK
(
j
.
size
()
==
1
);
CHECK
(
j
.
size
()
==
1
);
...
@@ -1002,7 +1002,7 @@ TEST_CASE("number (float)")
...
@@ -1002,7 +1002,7 @@ TEST_CASE("number (float)")
CHECK
(
j
.
cbegin
()
!=
j
.
cend
());
CHECK
(
j
.
cbegin
()
!=
j
.
cend
());
// string representation of default value
// string representation of default value
CHECK
(
j
.
to_string
()
==
"0.000000"
);
CHECK
(
j
.
dump
()
==
"0.000000"
);
// container members
// container members
CHECK
(
j
.
size
()
==
1
);
CHECK
(
j
.
size
()
==
1
);
...
@@ -1786,6 +1786,18 @@ TEST_CASE("Parser")
...
@@ -1786,6 +1786,18 @@ TEST_CASE("Parser")
CHECK
(
j22
==
j23
);
CHECK
(
j22
==
j23
);
}
}
SECTION
(
"serialization"
)
{
auto
j23
=
"{
\"
a
\"
: null,
\"
b
\"
: true,
\"
c
\"
: [1,2,3],
\"
d
\"
: {
\"
a
\"
: 0} }"
_json
;
CHECK
(
j23
.
dump
()
==
"{
\"
a
\"
: null,
\"
b
\"
: true,
\"
c
\"
: [1, 2, 3],
\"
d
\"
: {
\"
a
\"
: 0}}"
);
CHECK
(
j23
.
dump
(
-
1
)
==
"{
\"
a
\"
: null,
\"
b
\"
: true,
\"
c
\"
: [1, 2, 3],
\"
d
\"
: {
\"
a
\"
: 0}}"
);
CHECK
(
j23
.
dump
(
0
)
==
"{
\n\"
a
\"
: null,
\n\"
b
\"
: true,
\n\"
c
\"
: [
\n
1,
\n
2,
\n
3
\n
],
\n\"
d
\"
: {
\n\"
a
\"
: 0
\n
}
\n
}"
);
CHECK
(
j23
.
dump
(
4
)
==
"{
\n
\"
a
\"
: null,
\n
\"
b
\"
: true,
\n
\"
c
\"
: [
\n
1,
\n
2,
\n
3
\n
],
\n
\"
d
\"
: {
\n
\"
a
\"
: 0
\n
}
\n
}"
);
}
SECTION
(
"Errors"
)
SECTION
(
"Errors"
)
{
{
CHECK_THROWS_AS
(
json
::
parse
(
""
),
std
::
invalid_argument
);
CHECK_THROWS_AS
(
json
::
parse
(
""
),
std
::
invalid_argument
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment