Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
畅游知识海洋
json
提交
fe628b58
J
json
项目概览
畅游知识海洋
/
json
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
json
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
fe628b58
编写于
10月 17, 2016
作者:
T
Théo DELRIEU
提交者:
Théo DELRIEU
1月 21, 2017
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
anonymous namespace renamed to detail
上级
b443edf4
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
292 addition
and
19 deletion
+292
-19
src/json.hpp
src/json.hpp
+85
-8
test/src/unit-constructor3.cpp
test/src/unit-constructor3.cpp
+207
-11
未找到文件。
src/json.hpp
浏览文件 @
fe628b58
...
...
@@ -106,6 +106,14 @@ 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
;
...
...
@@ -113,8 +121,8 @@ struct json_traits;
@brief unnamed namespace with internal helper functions
@since version 1.0.0
*/
// TODO transform this anon ns to detail?
namespace
namespace
detail
{
/*!
@brief Helper to determine whether there's a key_type for T.
...
...
@@ -140,6 +148,7 @@ struct has_mapped_type
};
// taken from http://stackoverflow.com/questions/10711952/how-to-detect-existence-of-a-class-using-sfinae
// used to determine if json_traits is defined for a given type T
template
<
typename
T
>
struct
has_destructor
{
...
...
@@ -158,7 +167,23 @@ struct has_json_traits
static
constexpr
bool
value
=
has_destructor
<
json_traits
<
T
>>::
value
;
};
template
<
>
struct
has_json_traits
<
void
>
:
std
::
false_type
{};
struct
to_json_fn
{
template
<
typename
T
>
constexpr
auto
operator
()(
T
&&
val
)
const
->
decltype
(
to_json
(
std
::
forward
<
T
>
(
val
)))
{
return
to_json
(
std
::
forward
<
T
>
(
val
));
}
};
struct
from_json_fn
{
template
<
typename
Json
,
typename
T
>
constexpr
auto
operator
()(
Json
const
&
from
,
T
&
to
)
const
->
decltype
(
from_json
(
from
,
to
))
{
return
from_json
(
from
,
to
);
}
};
/*!
@brief helper class to create locales with decimal point
...
...
@@ -181,6 +206,23 @@ struct DecimalSeparator : std::numpunct<char>
};
// taken from ranges-v3
// TODO add doc
template
<
typename
T
>
struct
__static_const
{
static
constexpr
T
value
{};
};
template
<
typename
T
>
constexpr
T
__static_const
<
T
>::
value
;
inline
namespace
{
constexpr
auto
const
&
to_json
=
__static_const
<
detail
::
to_json_fn
>::
value
;
constexpr
auto
const
&
from_json
=
__static_const
<
detail
::
from_json_fn
>::
value
;
}
/*!
@brief a class to store JSON values
...
...
@@ -1337,10 +1379,24 @@ class basic_json
assert_invariant
();
}
// constructor chosen if json_traits is specialized for type T
// 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 expressivety 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
=
typename
std
::
enable_if
<
has_json_traits
<
typename
std
::
remove_cv
<
typename
std
::
enable_if
<
detail
::
has_json_traits
<
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
T
>
::
type
>::
type
>::
value
>::
type
>
explicit
basic_json
(
T
&&
val
)
:
basic_json
(
json_traits
<
typename
std
::
remove_cv
<
...
...
@@ -2705,10 +2761,13 @@ class basic_json
// value access //
//////////////////
// get_impl overload chosen if json_traits struct is specialized for type T
// simply returns json_traits<T>::from_json(*this);
// TODO add alias templates (enable_if_t etc)
template
<
typename
T
,
typename
=
typename
std
::
enable_if
<
has_json_traits
<
typename
std
::
remove_cv
<
typename
=
typename
std
::
enable_if
<
detail
::
has_json_traits
<
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
T
>
::
type
>::
type
>::
value
>::
type
>
auto
get_impl
(
T
*
)
const
->
decltype
(
json_traits
<
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
...
...
@@ -2717,6 +2776,24 @@ class basic_json
typename
std
::
remove_reference
<
T
>::
type
>::
type
>::
from_json
(
*
this
);
}
// this one is quite atrocious
// this overload is chosen ONLY if json_traits struct is not specialized, and if the expression nlohmann::from_json(*this, T&) is valid
// I chose to prefer the json_traits specialization if it exists, since it's a more advanced use.
// But we can of course change this behaviour
template
<
typename
T
>
auto
get_impl
(
T
*
)
const
->
typename
std
::
enable_if
<
not
detail
::
has_json_traits
<
typename
std
::
remove_cv
<
T
>::
type
>::
value
,
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
decltype
(
::
nlohmann
::
from_json
(
std
::
declval
<
basic_json
>
(),
std
::
declval
<
T
&>
()),
std
::
declval
<
T
>
())
>::
type
>::
type
>::
type
{
typename
std
::
remove_cv
<
typename
std
::
remove_reference
<
T
>::
type
>::
type
ret
;
::
nlohmann
::
from_json
(
*
this
,
ret
);
return
ret
;
}
/// get an object (explicit)
template
<
class
T
,
typename
std
::
enable_if
<
...
...
@@ -2750,7 +2827,7 @@ class basic_json
not
std
::
is_same
<
basic_json_t
,
typename
T
::
value_type
>::
value
and
not
std
::
is_arithmetic
<
T
>::
value
and
not
std
::
is_convertible
<
std
::
string
,
T
>::
value
and
not
has_mapped_type
<
T
>::
value
,
int
>::
type
=
0
>
not
detail
::
has_mapped_type
<
T
>::
value
,
int
>::
type
=
0
>
T
get_impl
(
T
*
/*unused*/
)
const
{
if
(
is_array
())
...
...
@@ -2791,7 +2868,7 @@ class basic_json
/// get an array (explicit)
template
<
class
T
,
typename
std
::
enable_if
<
std
::
is_same
<
basic_json
,
typename
T
::
value_type
>
::
value
and
not
has_mapped_type
<
T
>::
value
,
int
>::
type
=
0
>
not
detail
::
has_mapped_type
<
T
>::
value
,
int
>::
type
=
0
>
T
get_impl
(
T
*
/*unused*/
)
const
{
if
(
is_array
())
...
...
test/src/unit-constructor3.cpp
浏览文件 @
fe628b58
...
...
@@ -42,22 +42,12 @@ struct pod_type {
short
c
;
};
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
);
}
struct
bit_more_complex_type
{
pod_type
a
;
pod_type
b
;
std
::
string
c
;
};
inline
bool
operator
==
(
bit_more_complex_type
const
&
lhs
,
bit_more_complex_type
const
&
rhs
)
noexcept
{
return
std
::
tie
(
lhs
.
a
,
lhs
.
b
,
lhs
.
c
)
==
std
::
tie
(
rhs
.
a
,
rhs
.
b
,
rhs
.
c
);
}
// best optional implementation ever
template
<
typename
T
>
class
optional_type
...
...
@@ -68,11 +58,97 @@ public:
explicit
operator
bool
()
const
noexcept
{
return
_val
!=
nullptr
;
}
T
const
&
operator
*
()
const
{
return
*
_val
;
}
optional_type
&
operator
=
(
T
const
&
t
)
{
_val
=
std
::
make_shared
<
T
>
(
t
);
return
*
this
;
}
private:
std
::
shared_ptr
<
T
>
_val
;
};
struct
no_json_traits_type
{
int
a
;
};
// free to/from_json functions
json
to_json
(
empty_type
)
{
return
json
::
object
();
}
json
to_json
(
pod_type
const
&
p
)
{
return
{{
"a"
,
p
.
a
},
{
"b"
,
p
.
b
},
{
"c"
,
p
.
c
}};
}
json
to_json
(
bit_more_complex_type
const
&
p
)
{
using
nlohmann
::
to_json
;
return
json
{{
"a"
,
to_json
(
p
.
a
)},
{
"b"
,
to_json
(
p
.
b
)},
{
"c"
,
p
.
c
}};
}
template
<
typename
T
>
json
to_json
(
optional_type
<
T
>
const
&
opt
)
{
using
nlohmann
::
to_json
;
if
(
!
opt
)
return
nullptr
;
return
to_json
(
*
opt
);
}
json
to_json
(
no_json_traits_type
const
&
p
)
{
json
ret
;
ret
[
"a"
]
=
p
.
a
;
return
ret
;
}
void
from_json
(
json
const
&
j
,
empty_type
&
t
)
{
assert
(
j
.
empty
());
t
=
empty_type
{};
}
void
from_json
(
json
const
&
j
,
pod_type
&
t
)
{
t
=
{
j
[
"a"
].
get
<
int
>
(),
j
[
"b"
].
get
<
char
>
(),
j
[
"c"
].
get
<
short
>
()};
}
void
from_json
(
json
const
&
j
,
bit_more_complex_type
&
t
)
{
// relying on json_traits struct here..
t
=
{
j
[
"a"
].
get
<
udt
::
pod_type
>
(),
j
[
"b"
].
get
<
udt
::
pod_type
>
(),
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
)
{
if
(
j
.
is_null
())
t
=
optional_type
<
T
>
{};
else
t
=
j
.
get
<
T
>
();
}
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
);
}
inline
bool
operator
==
(
bit_more_complex_type
const
&
lhs
,
bit_more_complex_type
const
&
rhs
)
noexcept
{
return
std
::
tie
(
lhs
.
a
,
lhs
.
b
,
lhs
.
c
)
==
std
::
tie
(
rhs
.
a
,
rhs
.
b
,
rhs
.
c
);
}
template
<
typename
T
>
inline
bool
operator
==
(
optional_type
<
T
>
const
&
lhs
,
optional_type
<
T
>
const
&
rhs
)
{
...
...
@@ -82,6 +158,11 @@ 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
...
...
@@ -163,7 +244,7 @@ TEST_CASE("constructors for user-defined types", "[udt]")
{
SECTION
(
"empty type"
)
{
udt
::
empty_type
const
e
;
udt
::
empty_type
const
e
{}
;
auto
const
j
=
json
{
e
};
auto
k
=
json
::
object
();
CHECK
(
j
==
k
);
...
...
@@ -300,3 +381,118 @@ TEST_CASE("get<> for user-defined types", "[udt]")
}
}
}
TEST_CASE
(
"to_json free function"
,
"[udt]"
)
{
SECTION
(
"pod_type"
)
{
auto
const
e
=
udt
::
pod_type
{
42
,
42
,
42
};
auto
const
expected
=
json
{{
"a"
,
42
},
{
"b"
,
42
},
{
"c"
,
42
}};
auto
const
j
=
nlohmann
::
to_json
(
e
);
CHECK
(
j
==
expected
);
}
SECTION
(
"bit_more_complex_type"
)
{
auto
const
e
=
udt
::
bit_more_complex_type
{{
42
,
42
,
42
},
{
41
,
41
,
41
},
"forty"
};
auto
const
expected
=
json
{{
"a"
,
{{
"a"
,
42
},
{
"b"
,
42
},
{
"c"
,
42
}}},
{
"b"
,
{{
"a"
,
41
},
{
"b"
,
41
},
{
"c"
,
41
}}},
{
"c"
,
"forty"
}};
auto
const
j
=
nlohmann
::
to_json
(
e
);
CHECK
(
j
==
expected
);
}
SECTION
(
"optional_type"
)
{
SECTION
(
"from null"
)
{
udt
::
optional_type
<
udt
::
pod_type
>
o
;
json
expected
;
auto
const
j
=
nlohmann
::
to_json
(
o
);
CHECK
(
expected
==
j
);
}
SECTION
(
"from value"
)
{
udt
::
optional_type
<
udt
::
pod_type
>
o
{{
42
,
42
,
42
}};
auto
const
expected
=
json
{{
"a"
,
42
},
{
"b"
,
42
},
{
"c"
,
42
}};
auto
const
j
=
nlohmann
::
to_json
(
o
);
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]"
)
{
SECTION
(
"pod_type"
)
{
auto
const
expected
=
udt
::
pod_type
{
42
,
42
,
42
};
auto
const
j
=
json
{{
"a"
,
42
},
{
"b"
,
42
},
{
"c"
,
42
}};
udt
::
pod_type
p
;
nlohmann
::
from_json
(
j
,
p
);
CHECK
(
p
==
expected
);
}
SECTION
(
"bit_more_complex_type"
)
{
auto
const
expected
=
udt
::
bit_more_complex_type
{{
42
,
42
,
42
},
{
41
,
41
,
41
},
"forty"
};
auto
const
j
=
json
{{
"a"
,
{{
"a"
,
42
},
{
"b"
,
42
},
{
"c"
,
42
}}},
{
"b"
,
{{
"a"
,
41
},
{
"b"
,
41
},
{
"c"
,
41
}}},
{
"c"
,
"forty"
}};
udt
::
bit_more_complex_type
p
;
nlohmann
::
from_json
(
j
,
p
);
CHECK
(
p
==
expected
);
}
SECTION
(
"optional_type"
)
{
SECTION
(
"from null"
)
{
udt
::
optional_type
<
udt
::
pod_type
>
expected
;
json
j
;
udt
::
optional_type
<
udt
::
pod_type
>
o
;
nlohmann
::
from_json
(
j
,
o
);
CHECK
(
expected
==
o
);
}
SECTION
(
"from value"
)
{
udt
::
optional_type
<
udt
::
pod_type
>
expected
{{
42
,
42
,
42
}};
auto
const
j
=
json
{{
"a"
,
42
},
{
"b"
,
42
},
{
"c"
,
42
}};
udt
::
optional_type
<
udt
::
pod_type
>
o
;
nlohmann
::
from_json
(
j
,
o
);
CHECK
(
expected
==
o
);
}
}
SECTION
(
"no json_traits specialization"
)
{
udt
::
no_json_traits_type
expected
{
42
};
udt
::
no_json_traits_type
res
;
json
j
;
j
[
"a"
]
=
42
;
nlohmann
::
from_json
(
j
,
res
);
CHECK
(
res
==
expected
);
res
=
j
.
get
<
udt
::
no_json_traits_type
>
();
CHECK
(
res
==
expected
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录