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
7dc268ef
Commit
7dc268ef
authored
Nov 07, 2016
by
Théo DELRIEU
Committed by
Théo DELRIEU
Jan 21, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add first version for alternate implementation
parent
4cdc61e4
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
41 additions
and
262 deletions
+41
-262
json.hpp
src/json.hpp
+41
-90
unit-constructor3.cpp
test/src/unit-constructor3.cpp
+0
-172
No files found.
src/json.hpp
View file @
7dc268ef
...
...
@@ -106,17 +106,6 @@ SOFTWARE.
*/
namespace
nlohmann
{
// TODO add real documentation before PR
// Traits structure declaration, users can specialize it for their own types
//
// constructing a json object from a user-defined type will call the
// 'json to_json(T)' function
//
// whereas calling json::get<T> will call 'T from_json(json const&)'
template
<
typename
T
,
typename
=
void
>
struct
json_traits
;
// alias templates to reduce boilerplate
template
<
bool
B
,
typename
T
=
void
>
using
enable_if_t
=
typename
std
::
enable_if
<
B
,
T
>::
type
;
...
...
@@ -166,64 +155,24 @@ void from_json();
struct
to_json_fn
{
private
:
// fallback overload
template
<
typename
T
>
static
constexpr
auto
impl
(
T
&&
val
,
long
)
noexcept
(
noexcept
(
to_json
(
std
::
forward
<
T
>
(
val
))))
constexpr
auto
operator
()(
T
&&
val
)
const
noexcept
(
noexcept
(
to_json
(
std
::
forward
<
T
>
(
val
))))
->
decltype
(
to_json
(
std
::
forward
<
T
>
(
val
)))
{
return
to_json
(
std
::
forward
<
T
>
(
val
));
}
// preferred overload
template
<
typename
T
>
static
constexpr
auto
impl
(
T
&&
val
,
int
)
noexcept
(
noexcept
(
json_traits
<
uncvref_t
<
T
>>::
to_json
(
std
::
forward
<
T
>
(
val
))))
->
decltype
(
json_traits
<
uncvref_t
<
T
>>::
to_json
(
std
::
forward
<
T
>
(
val
)))
{
return
json_traits
<
uncvref_t
<
T
>>::
to_json
(
std
::
forward
<
T
>
(
val
));
}
public
:
template
<
typename
T
>
constexpr
auto
operator
()(
T
&&
val
)
const
noexcept
(
noexcept
(
to_json_fn
::
impl
(
std
::
forward
<
T
>
(
val
),
0
)))
->
decltype
(
to_json_fn
::
impl
(
std
::
forward
<
T
>
(
val
),
0
))
{
// decltype(0) -> int, so the compiler will try to take the 'preferred overload'
// if there is no specialization, the 'fallback overload' will be taken by converting 0 to long
return
to_json_fn
::
impl
(
std
::
forward
<
T
>
(
val
),
0
);
}
};
struct
from_json_fn
{
private
:
template
<
typename
T
,
typename
Json
>
static
constexpr
auto
impl
(
Json
const
&
j
,
T
&
val
,
long
)
noexcept
(
noexcept
(
from_json
(
j
,
val
)))
->
decltype
(
from_json
(
j
,
val
))
constexpr
auto
operator
()(
Json
&&
j
,
T
&
val
)
const
noexcept
(
noexcept
(
from_json
(
std
::
forward
<
Json
>
(
j
)
,
val
)))
->
decltype
(
from_json
(
std
::
forward
<
Json
>
(
j
)
,
val
))
{
return
from_json
(
j
,
val
);
}
template
<
typename
T
,
typename
Json
>
static
constexpr
auto
impl
(
Json
const
&
j
,
T
&
val
,
int
)
noexcept
(
noexcept
(
json_traits
<
T
>::
from_json
(
j
,
val
)))
->
decltype
(
json_traits
<
T
>::
from_json
(
j
,
val
))
{
return
json_traits
<
T
>::
from_json
(
j
,
val
);
}
public
:
template
<
typename
T
,
typename
Json
>
constexpr
auto
operator
()(
Json
const
&
j
,
T
&
val
)
const
noexcept
(
noexcept
(
from_json_fn
::
impl
(
j
,
val
,
0
)))
->
decltype
(
from_json_fn
::
impl
(
j
,
val
,
0
))
{
return
from_json_fn
::
impl
(
j
,
val
,
0
);
return
from_json
(
std
::
forward
<
Json
>
(
j
),
val
);
}
};
...
...
@@ -265,6 +214,32 @@ inline namespace
constexpr
auto
const
&
from_json
=
_static_const
<
detail
::
from_json_fn
>::
value
;
}
// default JSONSerializer template argument
// will use ADL for serialization
struct
adl_serializer
{
template
<
typename
T
,
typename
Json
,
typename
=
enable_if_t
<
std
::
is_default_constructible
<
uncvref_t
<
T
>>::
value
>>
static
auto
from_json
(
Json
&&
j
)
->
uncvref_t
<
decltype
(
::
nlohmann
::
from_json
(
std
::
forward
<
Json
>
(
j
),
std
::
declval
<
T
&>
()),
std
::
declval
<
T
>
())
>
{
uncvref_t
<
T
>
ret
;
::
nlohmann
::
from_json
(
std
::
forward
<
Json
>
(
j
),
ret
);
return
ret
;
}
template
<
typename
T
,
typename
Json
>
static
auto
from_json
(
Json
&&
j
,
T
&
val
)
->
decltype
(
::
nlohmann
::
from_json
(
std
::
forward
<
Json
>
(
j
),
val
))
{
::
nlohmann
::
from_json
(
std
::
forward
<
Json
>
(
j
),
val
);
}
template
<
typename
T
>
static
auto
to_json
(
T
&&
val
)
->
decltype
(
::
nlohmann
::
to_json
(
std
::
forward
<
T
>
(
val
)))
{
return
::
nlohmann
::
to_json
(
std
::
forward
<
T
>
(
val
));
}
};
/*!
@brief a class to store JSON values
...
...
@@ -352,7 +327,8 @@ template <
class
NumberIntegerType
=
std
::
int64_t
,
class
NumberUnsignedType
=
std
::
uint64_t
,
class
NumberFloatType
=
double
,
template
<
typename
U
>
class
AllocatorType
=
std
::
allocator
template
<
typename
U
>
class
AllocatorType
=
std
::
allocator
,
class
JSONSerializer
=
adl_serializer
>
class
basic_json
{
...
...
@@ -1421,30 +1397,10 @@ class basic_json
assert_invariant
();
}
// constructor chosen for user-defined types that either have:
// - a to_json free function in their type's namespace
// - a json_traits specialization for their type
//
// If there is both a free function and a specialization, the latter will be chosen,
// since it is a more advanced use
//
// note: constructor is marked explicit to avoid the following issue:
//
// struct not_equality_comparable{};
//
// not_equality_comparable{} == not_equality_comparable{};
//
// this will construct implicitely 2 json objects and call operator== on them
// which can cause nasty bugs on the user's in json-unrelated code
//
// the trade-off is expressiveness in initializer-lists
// auto j = json{{"a", json(not_equality_comparable{})}};
//
// we can remove this constraint though, since lots of ctor are not explicit already
template
<
typename
T
,
typename
=
decltype
(
::
nlohmann
::
to_json
(
std
::
declval
<
uncvref_t
<
T
>>
()))
>
// constructor chosen when JSONSerializer::to_json exists for type T
template
<
typename
T
,
typename
=
decltype
(
JSONSerializer
::
to_json
(
std
::
declval
<
uncvref_t
<
T
>>
()))
>
explicit
basic_json
(
T
&&
val
)
:
basic_json
(
::
nlohmann
::
to_json
(
std
::
forward
<
T
>
(
val
)))
{}
:
basic_json
(
JSONSerializer
::
to_json
(
std
::
forward
<
T
>
(
val
)))
{}
/*!
@brief create a string (explicit)
...
...
@@ -3115,16 +3071,11 @@ class basic_json
return
get_impl
(
static_cast
<
ValueType
*>
(
nullptr
));
}
template
<
typename
ValueType
>
auto
get
()
const
->
remove_reference_t
<
decltype
(
::
nlohmann
::
from_json
(
*
this
,
std
::
declval
<
ValueType
&>
()),
std
::
declval
<
ValueType
>
())
>
template
<
typename
ValueType
,
typename
=
enable_if_t
<
std
::
is_default_constructible
<
uncvref_t
<
ValueType
>>::
value
,
float
>>
auto
get
()
const
->
remove_reference_t
<
decltype
(
JSONSerializer
::
from_json
(
*
this
,
std
::
declval
<
ValueType
&>
()),
std
::
declval
<
ValueType
>
())
>
{
static_assert
(
std
::
is_default_constructible
<
ValueType
>::
value
,
"ValueType must be default-constructible when user-defined "
"from_json method is used"
);
ValueType
ret
;
::
nlohmann
::
from_json
(
*
this
,
ret
);
uncvref_t
<
ValueType
>
ret
;
JSONSerializer
::
from_json
(
*
this
,
ret
);
return
ret
;
}
...
...
test/src/unit-constructor3.cpp
View file @
7dc268ef
...
...
@@ -35,9 +35,6 @@ using nlohmann::json;
namespace
udt
{
// only used by counter_type
auto
nb_free_function_calls
=
0
;
struct
empty_type
{};
struct
pod_type
{
int
a
;
...
...
@@ -51,10 +48,6 @@ struct bit_more_complex_type {
std
::
string
c
;
};
struct
counter_type
{
};
// best optional implementation ever
template
<
typename
T
>
class
optional_type
...
...
@@ -75,11 +68,6 @@ private:
std
::
shared_ptr
<
T
>
_val
;
};
struct
no_json_traits_type
{
int
a
;
};
// free to/from_json functions
json
to_json
(
empty_type
)
...
...
@@ -107,17 +95,6 @@ json to_json(optional_type<T> const& opt)
return
json
(
*
opt
);
}
json
to_json
(
no_json_traits_type
const
&
p
)
{
return
{{
"a"
,
p
.
a
}};
}
json
to_json
(
counter_type
)
{
++
nb_free_function_calls
;
return
json
::
object
();
}
void
from_json
(
json
const
&
j
,
empty_type
&
t
)
{
assert
(
j
.
empty
());
...
...
@@ -136,11 +113,6 @@ void from_json(json const&j, bit_more_complex_type& t)
j
[
"c"
].
get
<
std
::
string
>
()};
}
void
from_json
(
json
const
&
j
,
no_json_traits_type
&
t
)
{
t
.
a
=
j
[
"a"
].
get
<
int
>
();
}
template
<
typename
T
>
void
from_json
(
json
const
&
j
,
optional_type
<
T
>&
t
)
{
...
...
@@ -150,11 +122,6 @@ void from_json(json const& j, optional_type<T>& t)
t
=
j
.
get
<
T
>
();
}
void
from_json
(
json
const
&
,
counter_type
&
)
{
++
nb_free_function_calls
;
}
inline
bool
operator
==
(
pod_type
const
&
lhs
,
pod_type
const
&
rhs
)
noexcept
{
return
std
::
tie
(
lhs
.
a
,
lhs
.
b
,
lhs
.
c
)
==
std
::
tie
(
rhs
.
a
,
rhs
.
b
,
rhs
.
c
);
...
...
@@ -174,107 +141,8 @@ inline bool operator==(optional_type<T> const& lhs, optional_type<T> const& rhs)
return
false
;
return
*
lhs
==
*
rhs
;
}
inline
bool
operator
==
(
no_json_traits_type
const
&
lhs
,
no_json_traits_type
const
&
rhs
)
{
return
lhs
.
a
==
rhs
.
a
;
}
}
namespace
nlohmann
{
template
<>
struct
json_traits
<
udt
::
empty_type
>
{
using
type
=
udt
::
empty_type
;
static
json
to_json
(
type
)
{
return
json
::
object
();
}
static
type
from_json
(
json
const
&
j
)
{
assert
(
j
.
is_object
()
and
j
.
empty
());
return
{};
}
};
template
<>
struct
json_traits
<
udt
::
pod_type
>
{
using
type
=
udt
::
pod_type
;
static
json
to_json
(
type
const
&
t
)
{
return
{{
"a"
,
t
.
a
},
{
"b"
,
t
.
b
},
{
"c"
,
t
.
c
}};
}
static
type
from_json
(
json
const
&
j
)
{
assert
(
j
.
is_object
());
return
{
j
[
"a"
].
get
<
int
>
(),
j
[
"b"
].
get
<
char
>
(),
j
[
"c"
].
get
<
short
>
()};
}
};
template
<>
struct
json_traits
<
udt
::
bit_more_complex_type
>
{
using
type
=
udt
::
bit_more_complex_type
;
static
json
to_json
(
type
const
&
t
)
{
return
json
{{
"a"
,
json
{
t
.
a
}},
{
"b"
,
json
{
t
.
b
}},
{
"c"
,
t
.
c
}};
}
static
type
from_json
(
json
const
&
j
)
{
return
{
j
[
"a"
].
get
<
udt
::
pod_type
>
(),
j
[
"b"
].
get
<
udt
::
pod_type
>
(),
j
[
"c"
].
get
<
std
::
string
>
()};
}
};
template
<
typename
T
>
struct
json_traits
<
udt
::
optional_type
<
T
>>
{
using
type
=
udt
::
optional_type
<
T
>
;
static
json
to_json
(
type
const
&
t
)
{
if
(
t
)
return
json
(
*
t
);
return
{};
}
static
type
from_json
(
json
const
&
j
)
{
if
(
j
.
is_null
())
return
{};
return
type
{
j
.
get
<
T
>
()};
}
};
template
<>
struct
json_traits
<
udt
::
counter_type
>
{
using
type
=
udt
::
counter_type
;
static
int
nb_calls
;
static
json
to_json
(
type
)
{
++
nb_calls
;
return
json
::
object
();
}
static
void
from_json
(
json
const
&
,
type
&
)
{
++
nb_calls
;
}
};
int
json_traits
<
udt
::
counter_type
>::
nb_calls
{
0
};
}
TEST_CASE
(
"constructors for user-defined types"
,
"[udt]"
)
{
SECTION
(
"empty type"
)
...
...
@@ -415,24 +283,6 @@ TEST_CASE("get<> for user-defined types", "[udt]")
CHECK
(
*
v
==
expected
);
}
}
SECTION
(
"no json_traits specialization, use of ADL"
)
{
udt
::
no_json_traits_type
val
{
42
};
auto
const
expected
=
json
{{
"a"
,
42
}};
auto
const
j
=
json
(
val
);
CHECK
(
j
==
expected
);
}
SECTION
(
"counter_type"
)
{
// check that the traits specialization is chosen
auto
const
j
=
json
{
udt
::
counter_type
{}};
CHECK
(
nlohmann
::
json_traits
<
udt
::
counter_type
>::
nb_calls
==
1
);
auto
const
elem
=
j
.
get
<
udt
::
counter_type
>
();
CHECK
(
nlohmann
::
json_traits
<
udt
::
counter_type
>::
nb_calls
==
2
);
CHECK
(
udt
::
nb_free_function_calls
==
0
);
}
}
TEST_CASE
(
"to_json free function"
,
"[udt]"
)
...
...
@@ -477,16 +327,6 @@ TEST_CASE("to_json free function", "[udt]")
CHECK
(
expected
==
j
);
}
}
SECTION
(
"no json_traits specialization"
)
{
udt
::
no_json_traits_type
t
{
42
};
json
expected
;
expected
[
"a"
]
=
42
;
auto
const
j
=
nlohmann
::
to_json
(
t
);
CHECK
(
j
==
expected
);
}
}
TEST_CASE
(
"from_json free function"
,
"[udt]"
)
...
...
@@ -535,16 +375,4 @@ TEST_CASE("from_json free function", "[udt]")
CHECK
(
expected
==
o
);
}
}
SECTION
(
"no json_traits specialization"
)
{
udt
::
no_json_traits_type
expected
{
42
};
udt
::
no_json_traits_type
res
;
auto
const
j
=
json
{{
"a"
,
42
}};
nlohmann
::
from_json
(
j
,
res
);
CHECK
(
res
==
expected
);
res
=
j
.
get
<
udt
::
no_json_traits_type
>
();
CHECK
(
res
==
expected
);
}
}
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