Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
json
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
json
Commits
3494014b
Commit
3494014b
authored
Jan 09, 2017
by
Théo DELRIEU
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
new unit-udt.cpp tests
parent
1f25ec5d
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
124 additions
and
59 deletions
+124
-59
test/src/unit-udt.cpp
test/src/unit-udt.cpp
+124
-59
No files found.
test/src/unit-udt.cpp
View file @
3494014b
...
@@ -391,27 +391,27 @@ TEST_CASE("adl_serializer specialization", "[udt]")
...
@@ -391,27 +391,27 @@ TEST_CASE("adl_serializer specialization", "[udt]")
namespace
nlohmann
namespace
nlohmann
{
{
// TODO provide a real example, since this works now :)
template
<
>
// template <typename T
>
struct
adl_serializer
<
std
::
vector
<
float
>
>
// struct adl_serializer<std::vector<T>>
{
// {
static
void
to_json
(
json
&
j
,
std
::
vector
<
float
>
const
&
)
// static void to_json(json& j, std::vector<T> const& opt)
{
// {
j
=
"hijacked!"
;
//
}
// }
//
static
void
from_json
(
json
const
&
,
std
::
vector
<
float
>&
opt
)
// static void from_json(json const& j, std::vector<T>& opt)
{
// {
opt
=
{
42.0
,
42.0
,
42.0
};
//
}
}
//
};
};
}
}
TEST_CASE
(
"
current supported types are preferred over specializations
"
,
"[udt]"
)
TEST_CASE
(
"
even supported types can be specialized
"
,
"[udt]"
)
{
{
json
j
=
std
::
vector
<
float
>
{
1.0
,
2.0
,
3.0
};
json
j
=
std
::
vector
<
int
>
{
1
,
2
,
3
}
;
CHECK
(
j
.
dump
()
==
R"("hijacked!")"
)
;
auto
f
=
j
.
get
<
std
::
vector
<
in
t
>>
();
auto
f
=
j
.
get
<
std
::
vector
<
floa
t
>>
();
CHECK
((
f
==
std
::
vector
<
int
>
{
1
,
2
,
3
}));
CHECK
((
f
==
std
::
vector
<
float
>
{
42.0
,
42.0
,
42.0
}));
}
}
namespace
nlohmann
namespace
nlohmann
...
@@ -432,7 +432,6 @@ struct adl_serializer<std::unique_ptr<T>>
...
@@ -432,7 +432,6 @@ struct adl_serializer<std::unique_ptr<T>>
}
}
// this is the overload needed for non-copyable types,
// this is the overload needed for non-copyable types,
// should we add a priority tag in the implementation to prefer this overload if it exists?
static
std
::
unique_ptr
<
T
>
from_json
(
json
const
&
j
)
static
std
::
unique_ptr
<
T
>
from_json
(
json
const
&
j
)
{
{
if
(
j
.
is_null
())
if
(
j
.
is_null
())
...
@@ -456,7 +455,7 @@ TEST_CASE("Non-copyable types", "[udt]")
...
@@ -456,7 +455,7 @@ TEST_CASE("Non-copyable types", "[udt]")
json
j
=
optPerson
;
json
j
=
optPerson
;
CHECK
(
j
.
is_null
());
CHECK
(
j
.
is_null
());
optPerson
.
reset
(
new
udt
::
person
{{
42
},
{
"John Doe"
}});
optPerson
.
reset
(
new
udt
::
person
{{
42
},
{
"John Doe"
}
,
udt
::
country
::
russia
});
j
=
optPerson
;
j
=
optPerson
;
CHECK_FALSE
(
j
.
is_null
());
CHECK_FALSE
(
j
.
is_null
());
...
@@ -465,7 +464,7 @@ TEST_CASE("Non-copyable types", "[udt]")
...
@@ -465,7 +464,7 @@ TEST_CASE("Non-copyable types", "[udt]")
SECTION
(
"from_json"
)
SECTION
(
"from_json"
)
{
{
auto
person
=
udt
::
person
{{
42
},
{
"John Doe"
}};
auto
person
=
udt
::
person
{{
42
},
{
"John Doe"
}
,
udt
::
country
::
russia
};
json
j
=
person
;
json
j
=
person
;
auto
optPerson
=
j
.
get
<
std
::
unique_ptr
<
udt
::
person
>>
();
auto
optPerson
=
j
.
get
<
std
::
unique_ptr
<
udt
::
person
>>
();
...
@@ -478,39 +477,70 @@ TEST_CASE("Non-copyable types", "[udt]")
...
@@ -478,39 +477,70 @@ TEST_CASE("Non-copyable types", "[udt]")
}
}
}
}
// custom serializer
// custom serializer - advanced usage
// advanced usage (I did not have a real use case in mind)
// pack structs that are pod-types (but not scalar types)
template
<
typename
T
,
typename
=
typename
std
::
enable_if
<
std
::
is_pod
<
T
>
::
value
>::
type
>
// relies on adl for any other type
template
<
typename
T
,
typename
=
void
>
struct
pod_serializer
struct
pod_serializer
{
{
template
<
typename
Json
>
// use adl for non-pods, or scalar types
static
void
from_json
(
Json
const
&
j
,
T
&
t
)
template
<
{
typename
Json
,
typename
U
=
T
,
std
::
uint64_t
value
;
typename
std
::
enable_if
<
// Why cannot we simply use: j.get<std::uint64_t>() ?
not
(
std
::
is_pod
<
U
>
::
value
and
std
::
is_class
<
U
>::
value
),
int
>::
type
=
0
>
// Well, with the current experiment, the get method looks for a from_json function, which we are currently defining!
static
void
from_json
(
Json
const
&
j
,
U
&
t
)
// This would end up in a stack overflow. Calling nlohmann::from_json is a workaround.
{
// I shall find a good way to avoid this once all constructors are converted to free methods
using
nlohmann
::
from_json
;
//
from_json
(
j
,
t
);
// In short, constructing a json by constructor calls to_json
}
// calling get calls from_json, for now, we cannot do this in custom serializers
nlohmann
::
from_json
(
j
,
value
);
// special behaviour for pods
auto
bytes
=
static_cast
<
char
*>
(
static_cast
<
void
*>
(
&
value
));
template
<
typename
Json
,
typename
U
=
T
,
std
::
memcpy
(
&
t
,
bytes
,
sizeof
(
value
));
typename
std
::
enable_if
<
}
std
::
is_pod
<
U
>
::
value
and
std
::
is_class
<
U
>::
value
,
int
>::
type
=
0
>
static
void
from_json
(
Json
const
&
j
,
U
&
t
)
template
<
typename
Json
>
{
static
void
to_json
(
Json
&
j
,
T
const
&
t
)
std
::
uint64_t
value
;
{
// TODO The following block is no longer relevant in this serializer, make another one that shows the issue
auto
bytes
=
static_cast
<
char
const
*>
(
static_cast
<
void
const
*>
(
&
t
));
// the problem arises only when one from_json method is defined without any constraint
std
::
uint64_t
value
=
bytes
[
0
];
//
for
(
auto
i
=
1
;
i
<
8
;
++
i
)
// Why cannot we simply use: j.get<std::uint64_t>() ?
{
// Well, with the current experiment, the get method looks for a from_json
value
|=
bytes
[
i
]
<<
8
*
i
;
// function, which we are currently defining!
}
// This would end up in a stack overflow. Calling nlohmann::from_json is a
// same thing here
// workaround (is it?).
nlohmann
::
to_json
(
j
,
value
);
// I shall find a good way to avoid this once all constructors are converted
}
// to free methods
//
// In short, constructing a json by constructor calls to_json
// calling get calls from_json, for now, we cannot do this in custom
// serializers
nlohmann
::
from_json
(
j
,
value
);
auto
bytes
=
static_cast
<
char
*>
(
static_cast
<
void
*>
(
&
value
));
std
::
memcpy
(
&
t
,
bytes
,
sizeof
(
value
));
}
template
<
typename
Json
,
typename
U
=
T
,
typename
std
::
enable_if
<
not
(
std
::
is_pod
<
U
>
::
value
and
std
::
is_class
<
U
>::
value
),
int
>::
type
=
0
>
static
void
to_json
(
Json
&
j
,
T
const
&
t
)
{
using
nlohmann
::
to_json
;
to_json
(
j
,
t
);
}
template
<
typename
Json
,
typename
U
=
T
,
typename
std
::
enable_if
<
std
::
is_pod
<
U
>
::
value
and
std
::
is_class
<
U
>::
value
,
int
>::
type
=
0
>
static
void
to_json
(
Json
&
j
,
T
const
&
t
)
noexcept
{
auto
bytes
=
static_cast
<
unsigned
char
const
*>
(
static_cast
<
void
const
*>
(
&
t
));
std
::
uint64_t
value
=
bytes
[
0
];
for
(
auto
i
=
1
;
i
<
8
;
++
i
)
value
|=
std
::
uint64_t
{
bytes
[
i
]}
<<
8
*
i
;
nlohmann
::
to_json
(
j
,
value
);
}
};
};
namespace
udt
namespace
udt
...
@@ -522,23 +552,58 @@ struct small_pod
...
@@ -522,23 +552,58 @@ struct small_pod
short
end
;
short
end
;
};
};
bool
operator
==
(
small_pod
lhs
,
small_pod
rhs
)
struct
non_pod
{
std
::
string
s
;
};
template
<
typename
Json
>
void
to_json
(
Json
&
j
,
non_pod
const
&
np
)
{
j
=
np
.
s
;
}
template
<
typename
Json
>
void
from_json
(
Json
const
&
j
,
non_pod
&
np
)
{
np
.
s
=
j
.
template
get
<
std
::
string
>();
}
bool
operator
==
(
small_pod
lhs
,
small_pod
rhs
)
noexcept
{
{
return
std
::
tie
(
lhs
.
begin
,
lhs
.
middle
,
lhs
.
end
)
==
return
std
::
tie
(
lhs
.
begin
,
lhs
.
middle
,
lhs
.
end
)
==
std
::
tie
(
lhs
.
begin
,
lhs
.
middle
,
lhs
.
end
);
std
::
tie
(
rhs
.
begin
,
rhs
.
middle
,
rhs
.
end
);
}
bool
operator
==
(
non_pod
const
&
lhs
,
non_pod
const
&
rhs
)
noexcept
{
return
lhs
.
s
==
rhs
.
s
;
}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
small_pod
l
)
{
return
os
<<
"begin: "
<<
l
.
begin
<<
", middle: "
<<
l
.
middle
<<
", end: "
<<
l
.
end
;
}
}
}
}
TEST_CASE
(
"custom serializer for pods"
,
"[udt]"
)
TEST_CASE
(
"custom serializer for pods"
,
"[udt]"
)
{
{
using
custom_json
=
nlohmann
::
basic_json
<
std
::
map
,
std
::
vector
,
std
::
string
,
bool
,
std
::
int64_t
,
std
::
uint64_t
,
double
,
std
::
allocator
,
pod_serializer
>
;
using
custom_json
=
nlohmann
::
basic_json
<
std
::
map
,
std
::
vector
,
std
::
string
,
bool
,
std
::
int64_t
,
std
::
uint64_t
,
double
,
std
::
allocator
,
pod_serializer
>
;
auto
p
=
udt
::
small_pod
{
42
,
'/'
,
42
};
custom_json
j
=
p
;
auto
p
=
udt
::
small_pod
{
42
,
'/'
,
42
};
auto
p2
=
j
.
get
<
udt
::
small_pod
>
();
custom_json
j
=
p
;
auto
p2
=
j
.
get
<
udt
::
small_pod
>
(
);
CHECK
(
p
==
p2
);
CHECK
(
p
==
p2
);
auto
np
=
udt
::
non_pod
{{
"non-pod"
}};
custom_json
j2
=
np
;
auto
np2
=
j2
.
get
<
udt
::
non_pod
>
();
CHECK
(
np
==
np2
);
}
}
template
<
typename
T
,
typename
>
template
<
typename
T
,
typename
>
...
...
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