Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
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
Operations
Operations
Metrics
Environments
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
cpp-libs
Actor Framework
Commits
f453061e
Commit
f453061e
authored
Feb 22, 2021
by
Dominik Charousset
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support variant fields in the json_writer
parent
2ede8ae0
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
185 additions
and
15 deletions
+185
-15
libcaf_core/caf/json_writer.hpp
libcaf_core/caf/json_writer.hpp
+18
-2
libcaf_core/src/json_writer.cpp
libcaf_core/src/json_writer.cpp
+49
-11
libcaf_core/test/core-test.hpp
libcaf_core/test/core-test.hpp
+46
-2
libcaf_core/test/json_writer.cpp
libcaf_core/test/json_writer.cpp
+72
-0
No files found.
libcaf_core/caf/json_writer.hpp
View file @
f453061e
...
@@ -35,10 +35,12 @@ public:
...
@@ -35,10 +35,12 @@ public:
// -- constants --------------------------------------------------------------
// -- constants --------------------------------------------------------------
/// The value returned for `skip_empty_fields()` for a default-constructed
/// The default value for `skip_empty_fields()`.
/// JSON writer.
static
constexpr
bool
skip_empty_fields_default
=
true
;
static
constexpr
bool
skip_empty_fields_default
=
true
;
/// The value value for `field_type_suffix()`.
static
constexpr
string_view
field_type_suffix_default
=
"-type"
;
// -- constructors, destructors, and assignment operators --------------------
// -- constructors, destructors, and assignment operators --------------------
json_writer
();
json_writer
();
...
@@ -88,6 +90,18 @@ public:
...
@@ -88,6 +90,18 @@ public:
skip_empty_fields_
=
value
;
skip_empty_fields_
=
value
;
}
}
/// Returns the suffix for generating type annotation fields for variant
/// fields. For example, CAF inserts field called "@foo${field_type_suffix}"
/// for a variant field called "foo".
[[
nodiscard
]]
string_view
field_type_suffix
()
const
noexcept
{
return
field_type_suffix_
;
}
/// Configures whether the writer omits empty fields.
void
field_type_suffix
(
string_view
suffix
)
noexcept
{
field_type_suffix_
=
suffix
;
}
// -- modifiers --------------------------------------------------------------
// -- modifiers --------------------------------------------------------------
/// Removes all characters from the buffer and restores the writer to its
/// Removes all characters from the buffer and restores the writer to its
...
@@ -249,6 +263,8 @@ private:
...
@@ -249,6 +263,8 @@ private:
// Configures whether we omit empty fields entirely (true) or render empty
// Configures whether we omit empty fields entirely (true) or render empty
// fields as `$field: null` (false).
// fields as `$field: null` (false).
bool
skip_empty_fields_
=
skip_empty_fields_default
;
bool
skip_empty_fields_
=
skip_empty_fields_default
;
string_view
field_type_suffix_
=
field_type_suffix_default
;
};
};
}
// namespace caf
}
// namespace caf
libcaf_core/src/json_writer.cpp
View file @
f453061e
...
@@ -79,13 +79,21 @@ void json_writer::reset() {
...
@@ -79,13 +79,21 @@ void json_writer::reset() {
// -- overrides ----------------------------------------------------------------
// -- overrides ----------------------------------------------------------------
bool
json_writer
::
begin_object
(
type_id_t
,
string_view
name
)
{
bool
json_writer
::
begin_object
(
type_id_t
id
,
string_view
name
)
{
auto
add_type_annotation
=
[
this
,
name
]
{
auto
add_type_annotation
=
[
this
,
id
,
name
]
{
CAF_ASSERT
(
top
()
==
type
::
key
);
CAF_ASSERT
(
top
()
==
type
::
key
);
add
(
R"_("@type": )_"
);
add
(
R"_("@type": )_"
);
pop
();
pop
();
CAF_ASSERT
(
top
()
==
type
::
element
);
CAF_ASSERT
(
top
()
==
type
::
element
);
detail
::
print_escaped
(
buf_
,
name
);
if
(
auto
tname
=
query_type_name
(
id
);
!
tname
.
empty
())
{
add
(
'"'
);
add
(
tname
);
add
(
'"'
);
}
else
{
add
(
'"'
);
add
(
name
);
add
(
'"'
);
}
pop
();
pop
();
return
true
;
return
true
;
};
};
...
@@ -105,8 +113,9 @@ bool json_writer::end_object() {
...
@@ -105,8 +113,9 @@ bool json_writer::end_object() {
bool
json_writer
::
begin_field
(
string_view
name
)
{
bool
json_writer
::
begin_field
(
string_view
name
)
{
if
(
begin_key_value_pair
())
{
if
(
begin_key_value_pair
())
{
CAF_ASSERT
(
top
()
==
type
::
key
);
CAF_ASSERT
(
top
()
==
type
::
key
);
detail
::
print_escaped
(
buf_
,
name
);
add
(
'"'
);
add
(
": "
);
add
(
name
);
add
(
"
\"
: "
);
pop
();
pop
();
CAF_ASSERT
(
top
()
==
type
::
element
);
CAF_ASSERT
(
top
()
==
type
::
element
);
return
true
;
return
true
;
...
@@ -131,8 +140,9 @@ bool json_writer::begin_field(string_view name, bool is_present) {
...
@@ -131,8 +140,9 @@ bool json_writer::begin_field(string_view name, bool is_present) {
}
}
}
else
if
(
begin_key_value_pair
())
{
}
else
if
(
begin_key_value_pair
())
{
CAF_ASSERT
(
top
()
==
type
::
key
);
CAF_ASSERT
(
top
()
==
type
::
key
);
detail
::
print_escaped
(
buf_
,
name
);
add
(
'"'
);
add
(
": "
);
add
(
name
);
add
(
"
\"
: "
);
pop
();
pop
();
CAF_ASSERT
(
top
()
==
type
::
element
);
CAF_ASSERT
(
top
()
==
type
::
element
);
if
(
!
is_present
)
{
if
(
!
is_present
)
{
...
@@ -145,13 +155,41 @@ bool json_writer::begin_field(string_view name, bool is_present) {
...
@@ -145,13 +155,41 @@ bool json_writer::begin_field(string_view name, bool is_present) {
}
}
}
}
bool
json_writer
::
begin_field
(
string_view
name
,
span
<
const
type_id_t
>
,
size_t
)
{
bool
json_writer
::
begin_field
(
string_view
name
,
span
<
const
type_id_t
>
types
,
return
begin_field
(
name
);
size_t
index
)
{
if
(
index
>=
types
.
size
())
{
emplace_error
(
sec
::
runtime_error
,
"index >= types.size()"
);
return
false
;
}
if
(
begin_key_value_pair
())
{
CAF_ASSERT
(
top
()
==
type
::
key
);
add
(
"
\"
@"
);
add
(
name
);
add
(
field_type_suffix_
);
add
(
"
\"
: "
);
pop
();
CAF_ASSERT
(
top
()
==
type
::
element
);
pop
();
if
(
auto
tname
=
query_type_name
(
types
[
index
]);
!
tname
.
empty
())
{
add
(
'"'
);
add
(
tname
);
add
(
'"'
);
}
else
{
emplace_error
(
sec
::
runtime_error
,
"query_type_name failed"
);
return
false
;
}
return
end_key_value_pair
()
&&
begin_field
(
name
);
}
else
{
return
false
;
}
}
}
bool
json_writer
::
begin_field
(
string_view
name
,
bool
is_present
,
bool
json_writer
::
begin_field
(
string_view
name
,
bool
is_present
,
span
<
const
type_id_t
>
,
size_t
)
{
span
<
const
type_id_t
>
types
,
size_t
index
)
{
return
begin_field
(
name
,
is_present
);
if
(
is_present
)
return
begin_field
(
name
,
types
,
index
);
else
return
begin_field
(
name
,
is_present
);
}
}
bool
json_writer
::
end_field
()
{
bool
json_writer
::
end_field
()
{
...
...
libcaf_core/test/core-test.hpp
View file @
f453061e
...
@@ -298,8 +298,8 @@ bool inspect(Inspector& f, dummy_enum& x) {
...
@@ -298,8 +298,8 @@ bool inspect(Inspector& f, dummy_enum& x) {
}
}
struct
point
{
struct
point
{
int
x
;
int
32_t
x
;
int
y
;
int
32_t
y
;
};
};
[[
maybe_unused
]]
constexpr
bool
operator
==
(
point
a
,
point
b
)
noexcept
{
[[
maybe_unused
]]
constexpr
bool
operator
==
(
point
a
,
point
b
)
noexcept
{
...
@@ -336,6 +336,48 @@ bool inspect(Inspector& f, rectangle& x) {
...
@@ -336,6 +336,48 @@ bool inspect(Inspector& f, rectangle& x) {
return
!
(
x
==
y
);
return
!
(
x
==
y
);
}
}
struct
circle
{
point
center
;
int32_t
radius
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
circle
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"center"
,
x
.
center
),
f
.
field
(
"radius"
,
x
.
radius
));
}
[[
maybe_unused
]]
constexpr
bool
operator
==
(
const
circle
&
x
,
const
circle
&
y
)
noexcept
{
return
x
.
center
==
y
.
center
&&
x
.
radius
==
y
.
radius
;
}
[[
maybe_unused
]]
constexpr
bool
operator
!=
(
const
circle
&
x
,
const
circle
&
y
)
noexcept
{
return
!
(
x
==
y
);
}
struct
widget
{
std
::
string
color
;
caf
::
variant
<
rectangle
,
circle
>
shape
;
};
template
<
class
Inspector
>
bool
inspect
(
Inspector
&
f
,
widget
&
x
)
{
return
f
.
object
(
x
).
fields
(
f
.
field
(
"color"
,
x
.
color
),
f
.
field
(
"shape"
,
x
.
shape
));
}
[[
maybe_unused
]]
inline
bool
operator
==
(
const
widget
&
x
,
const
widget
&
y
)
noexcept
{
return
x
.
color
==
y
.
color
&&
x
.
shape
==
y
.
shape
;
}
[[
maybe_unused
]]
inline
bool
operator
!=
(
const
widget
&
x
,
const
widget
&
y
)
noexcept
{
return
!
(
x
==
y
);
}
struct
dummy_user
{
struct
dummy_user
{
std
::
string
name
;
std
::
string
name
;
caf
::
optional
<
std
::
string
>
nickname
;
caf
::
optional
<
std
::
string
>
nickname
;
...
@@ -378,6 +420,7 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_test, caf::first_custom_type_id)
...
@@ -378,6 +420,7 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_test, caf::first_custom_type_id)
ADD_TYPE_ID
((
caf
::
stream
<
int32_t
>
)
)
ADD_TYPE_ID
((
caf
::
stream
<
int32_t
>
)
)
ADD_TYPE_ID
((
caf
::
stream
<
std
::
pair
<
level
,
std
::
string
>>
)
)
ADD_TYPE_ID
((
caf
::
stream
<
std
::
pair
<
level
,
std
::
string
>>
)
)
ADD_TYPE_ID
((
caf
::
stream
<
std
::
string
>
)
)
ADD_TYPE_ID
((
caf
::
stream
<
std
::
string
>
)
)
ADD_TYPE_ID
((
circle
))
ADD_TYPE_ID
((
dummy_enum
))
ADD_TYPE_ID
((
dummy_enum
))
ADD_TYPE_ID
((
dummy_enum_class
))
ADD_TYPE_ID
((
dummy_enum_class
))
ADD_TYPE_ID
((
dummy_struct
))
ADD_TYPE_ID
((
dummy_struct
))
...
@@ -410,6 +453,7 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_test, caf::first_custom_type_id)
...
@@ -410,6 +453,7 @@ CAF_BEGIN_TYPE_ID_BLOCK(core_test, caf::first_custom_type_id)
ADD_TYPE_ID
((
test_array
))
ADD_TYPE_ID
((
test_array
))
ADD_TYPE_ID
((
test_empty_non_pod
))
ADD_TYPE_ID
((
test_empty_non_pod
))
ADD_TYPE_ID
((
test_enum
))
ADD_TYPE_ID
((
test_enum
))
ADD_TYPE_ID
((
widget
))
ADD_ATOM
(
abc_atom
)
ADD_ATOM
(
abc_atom
)
ADD_ATOM
(
get_state_atom
)
ADD_ATOM
(
get_state_atom
)
...
...
libcaf_core/test/json_writer.cpp
View file @
f453061e
...
@@ -224,4 +224,76 @@ SCENARIO("the JSON writer omits or nulls missing values") {
...
@@ -224,4 +224,76 @@ SCENARIO("the JSON writer omits or nulls missing values") {
}
}
}
}
SCENARIO
(
"the JSON writer annotates variant fields"
)
{
GIVEN
(
"a widget object with rectangle shape"
)
{
widget
x
;
x
.
color
=
"red"
;
x
.
shape
=
rectangle
{{
10
,
10
},
{
20
,
20
}};
WHEN
(
"converting it to JSON with indentation factor 0"
)
{
THEN
(
"the JSON is a single line containing '@shape-type = rectangle'"
)
{
std
::
string
out
=
R"({"@type": "widget", )"
R"("color": "red", )"
R"("@shape-type": "rectangle", )"
R"("shape": )"
R"({"top-left": {"x": 10, "y": 10}, )"
R"("bottom-right": {"x": 20, "y": 20}}})"
;
CHECK_EQ
(
to_json_string
(
x
,
0
),
out
);
}
}
WHEN
(
"converting it to JSON with indentation factor 2"
)
{
THEN
(
"the JSON is multiple lines containing '@shape-type = rectangle'"
)
{
std
::
string
out
=
R"({
"@type": "widget",
"color": "red",
"@shape-type": "rectangle",
"shape": {
"top-left": {
"x": 10,
"y": 10
},
"bottom-right": {
"x": 20,
"y": 20
}
}
})"
;
CHECK_EQ
(
to_json_string
(
x
,
2
),
out
);
}
}
}
GIVEN
(
"a widget object with circle shape"
)
{
widget
x
;
x
.
color
=
"red"
;
x
.
shape
=
circle
{{
15
,
15
},
5
};
WHEN
(
"converting it to JSON with indentation factor 0"
)
{
THEN
(
"the JSON is a single line containing '@shape-type = circle'"
)
{
std
::
string
out
=
R"({"@type": "widget", )"
R"("color": "red", )"
R"("@shape-type": "circle", )"
R"("shape": )"
R"({"center": {"x": 15, "y": 15}, )"
R"("radius": 5}})"
;
CHECK_EQ
(
to_json_string
(
x
,
0
),
out
);
}
}
WHEN
(
"converting it to JSON with indentation factor 2"
)
{
THEN
(
"the JSON is multiple lines containing '@shape-type = circle'"
)
{
std
::
string
out
=
R"({
"@type": "widget",
"color": "red",
"@shape-type": "circle",
"shape": {
"center": {
"x": 15,
"y": 15
},
"radius": 5
}
})"
;
CHECK_EQ
(
to_json_string
(
x
,
2
),
out
);
}
}
}
}
CAF_TEST_FIXTURE_SCOPE_END
()
CAF_TEST_FIXTURE_SCOPE_END
()
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