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
3d405c68
Commit
3d405c68
authored
Dec 14, 2016
by
Théo DELRIEU
Committed by
Théo DELRIEU
Jan 21, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add support for enum classes
parent
8e43d476
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
71 additions
and
12 deletions
+71
-12
json.hpp
src/json.hpp
+18
-3
unit-udt.cpp
test/src/unit-udt.cpp
+53
-9
No files found.
src/json.hpp
View file @
3d405c68
...
...
@@ -122,6 +122,17 @@ using uncvref_t = remove_cv_t<remove_reference_t<T>>;
template
<
bool
If
,
typename
Then
,
typename
Else
>
using
conditional_t
=
typename
std
::
conditional
<
If
,
Then
,
Else
>::
type
;
// Taken from http://stackoverflow.com/questions/26936640/how-to-implement-is-enum-class-type-trait
template
<
typename
T
>
using
is_scoped_enum
=
std
::
integral_constant
<
bool
,
not
std
::
is_convertible
<
T
,
int
>::
value
and
std
::
is_enum
<
T
>::
value
>
;
template
<
typename
T
>
using
is_unscoped_enum
=
std
::
integral_constant
<
bool
,
std
::
is_convertible
<
T
,
int
>::
value
and
std
::
is_enum
<
T
>::
value
>
;
// TODO update this doc
/*!
@brief unnamed namespace with internal helper functions
...
...
@@ -130,6 +141,10 @@ using conditional_t = typename std::conditional<If, Then, Else>::type;
namespace
detail
{
// Very useful construct against boilerplate (more boilerplate needed than in C++17: http://en.cppreference.com/w/cpp/types/void_t)
template
<
typename
...
>
struct
make_void
{
using
type
=
void
;
};
template
<
typename
...
Ts
>
using
void_t
=
typename
make_void
<
Ts
...
>::
type
;
// Implementation of 3 C++17 constructs: conjunction, disjunction, negation.
// This is needed to avoid evaluating all the traits in a condition
//
...
...
@@ -277,6 +292,7 @@ template <typename T, typename BasicJson>
struct
is_compatible_basic_json_type
{
static
auto
constexpr
value
=
is_unscoped_enum
<
T
>::
value
or
std
::
is_same
<
T
,
BasicJson
>::
value
or
std
::
is_constructible
<
typename
BasicJson
::
string_t
,
T
>::
value
or
std
::
is_same
<
typename
BasicJson
::
boolean_t
,
T
>::
value
or
...
...
@@ -1601,7 +1617,6 @@ class basic_json
not
detail
::
is_compatible_basic_json_type
<
uncvref_t
<
T
>
,
basic_json_t
>::
value
and
not
detail
::
is_basic_json_nested_class
<
uncvref_t
<
T
>
,
basic_json_t
,
primitive_iterator_t
>::
value
and
not
std
::
is_enum
<
uncvref_t
<
T
>>::
value
and
not
std
::
is_same
<
uncvref_t
<
T
>
,
typename
basic_json_t
::
array_t
::
iterator
>::
value
and
not
std
::
is_same
<
uncvref_t
<
T
>
,
typename
basic_json_t
::
object_t
::
iterator
>::
value
and
detail
::
has_to_json
<
JSONSerializer
,
basic_json
,
...
...
@@ -1774,8 +1789,8 @@ class basic_json
@since version 1.0.0
*/
//
Quickfix, accept every enum type, without looking if a to_json method is provided...
template
<
typename
T
,
enable_if_t
<
std
::
is
_enum
<
T
>::
value
,
int
>
=
0
>
//
Constructor for unscoped enums (not enum classes)
template
<
typename
T
,
enable_if_t
<
is_unscoped
_enum
<
T
>::
value
,
int
>
=
0
>
basic_json
(
T
val
)
noexcept
:
m_type
(
value_t
::
number_integer
),
m_value
(
static_cast
<
number_integer_t
>
(
val
))
...
...
test/src/unit-udt.cpp
View file @
3d405c68
...
...
@@ -35,6 +35,13 @@ SOFTWARE.
namespace
udt
{
enum
class
country
{
china
,
france
,
russia
};
struct
age
{
int
m_val
;
...
...
@@ -54,6 +61,7 @@ namespace udt
{
age
m_age
;
name
m_name
;
country
m_country
;
};
struct
contact
...
...
@@ -69,7 +77,7 @@ namespace udt
};
}
// to_json methods
for default basic_json
// to_json methods
namespace
udt
{
void
to_json
(
nlohmann
::
json
&
j
,
age
a
)
...
...
@@ -82,10 +90,26 @@ namespace udt
j
=
n
.
m_val
;
}
void
to_json
(
nlohmann
::
json
&
j
,
country
c
)
{
switch
(
c
)
{
case
country
:
:
china
:
j
=
u8"中华人民共和国"
;
return
;
case
country
:
:
france
:
j
=
"France"
;
return
;
case
country
:
:
russia
:
j
=
u8"Российская Федерация"
;
return
;
}
}
void
to_json
(
nlohmann
::
json
&
j
,
person
const
&
p
)
{
using
nlohmann
::
json
;
j
=
json
{{
"age"
,
p
.
m_age
},
{
"name"
,
p
.
m_name
}};
j
=
json
{{
"age"
,
p
.
m_age
},
{
"name"
,
p
.
m_name
}
,
{
"country"
,
p
.
m_country
}
};
}
void
to_json
(
nlohmann
::
json
&
j
,
address
const
&
a
)
...
...
@@ -139,7 +163,7 @@ namespace udt
}
}
// from_json methods
for default basic_json
// from_json methods
namespace
udt
{
void
from_json
(
nlohmann
::
json
const
&
j
,
age
&
a
)
...
...
@@ -152,10 +176,24 @@ namespace udt
n
.
m_val
=
j
.
get
<
std
::
string
>
();
}
void
from_json
(
nlohmann
::
json
const
&
j
,
country
&
c
)
{
const
auto
str
=
j
.
get
<
std
::
string
>
();
static
const
std
::
map
<
std
::
string
,
country
>
m
=
{
{
u8"中华人民共和国"
,
country
::
china
},
{
"France"
,
country
::
france
},
{
"Российская Федерация"
,
country
::
russia
}};
const
auto
it
=
m
.
find
(
str
);
// TODO test exceptions
c
=
it
->
second
;
}
void
from_json
(
nlohmann
::
json
const
&
j
,
person
&
p
)
{
p
.
m_age
=
j
[
"age"
].
get
<
age
>
();
p
.
m_name
=
j
[
"name"
].
get
<
name
>
();
p
.
m_country
=
j
[
"country"
].
get
<
country
>
();
}
void
from_json
(
nlohmann
::
json
const
&
j
,
address
&
a
)
...
...
@@ -183,29 +221,33 @@ TEST_CASE("basic usage", "[udt]")
// a bit narcissic maybe :) ?
const
udt
::
age
a
{
23
};
const
udt
::
name
n
{
"theo"
};
const
udt
::
person
sfinae_addict
{
a
,
n
};
const
udt
::
country
c
{
udt
::
country
::
france
};
const
udt
::
person
sfinae_addict
{
a
,
n
,
c
};
const
udt
::
person
senior_programmer
{{
42
},
{
u8"王芳"
},
udt
::
country
::
china
};
const
udt
::
address
addr
{
"Paris"
};
const
udt
::
contact
cpp_programmer
{
sfinae_addict
,
addr
};
const
udt
::
contact_book
book
{{
"C++"
},
{
cpp_programmer
,
cpp_programmer
}};
const
udt
::
contact_book
book
{{
"C++"
},
{
cpp_programmer
,
{
senior_programmer
,
addr
}
}};
SECTION
(
"conversion to json via free-functions"
)
{
CHECK
(
json
(
a
)
==
json
(
23
));
CHECK
(
json
(
n
)
==
json
(
"theo"
));
CHECK
(
json
(
sfinae_addict
)
==
R"({"name":"theo", "age":23})"
_json
);
CHECK
(
json
(
c
)
==
json
(
"France"
));
CHECK
(
json
(
sfinae_addict
)
==
R"({"name":"theo", "age":23, "country":"France"})"
_json
);
CHECK
(
json
(
"Paris"
)
==
json
(
addr
));
CHECK
(
json
(
cpp_programmer
)
==
R"({"person" : {"age":23, "name":"theo"}, "address":"Paris"})"
_json
);
R"({"person" : {"age":23, "name":"theo"
, "country":"France"
}, "address":"Paris"})"
_json
);
CHECK
(
json
(
book
)
==
R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo"}, "address":"Paris"}, {"person" : {"age":23, "name":"theo"}, "address":"Paris"}]})"
_json
);
R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo", "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳"}, "address":"Paris"}]})"
_json
);
}
SECTION
(
"conversion from json via free-functions"
)
{
const
auto
big_json
=
R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo"
}, "address":"Paris"}, {"person" : {"age":23, "name":"theo
"}, "address":"Paris"}]})"
_json
;
R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo"
, "country":"France"}, "address":"Paris"}, {"person" : {"age":42, "country":"中华人民共和国", "name":"王芳
"}, "address":"Paris"}]})"
_json
;
const
auto
parsed_book
=
big_json
.
get
<
udt
::
contact_book
>
();
const
auto
book_name
=
big_json
[
"name"
].
get
<
udt
::
name
>
();
const
auto
contacts
=
big_json
[
"contacts"
].
get
<
std
::
vector
<
udt
::
contact
>>
();
...
...
@@ -214,10 +256,12 @@ TEST_CASE("basic usage", "[udt]")
const
auto
person
=
contact_json
[
"person"
].
get
<
udt
::
person
>
();
const
auto
address
=
contact_json
[
"address"
].
get
<
udt
::
address
>
();
const
auto
age
=
contact_json
[
"person"
][
"age"
].
get
<
udt
::
age
>
();
const
auto
country
=
contact_json
[
"person"
][
"country"
].
get
<
udt
::
country
>
();
const
auto
name
=
contact_json
[
"person"
][
"name"
].
get
<
udt
::
name
>
();
CHECK
(
age
==
a
);
CHECK
(
name
==
n
);
CHECK
(
country
==
c
);
CHECK
(
address
==
addr
);
CHECK
(
person
==
sfinae_addict
);
CHECK
(
contact
==
cpp_programmer
);
...
...
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