Serialization: Correctly encode structs with no fields

Empty structs were being serialized as `null`, when they should have been serialized as `{}`.

This was due to the type inference on the serializer - where no calls to `field()` would result in the default `null` type.

To solve this, the `serialize(const void* object, const std::initializer_list<Field>&)` inline helper has been promoted to a virtual function (and renamed to `fields()`).
The JSON serializer implementation of this now first sets the object type to `object`, even if there are no fields to serialize.

Added test for this.

Fixes: #10
This commit is contained in:
Ben Clayton
2020-01-05 09:25:43 +00:00
parent 3a10d4cabd
commit cdc19ac4d9
5 changed files with 30 additions and 22 deletions

View File

@@ -224,6 +224,19 @@ bool Serializer::array(size_t count,
return true;
}
bool Serializer::fields(const void* object,
const std::initializer_list<Field>& fields) {
*json = nlohmann::json({}, false, nlohmann::json::value_t::object);
for (auto const& f : fields) {
if (!field(f.name, [&](dap::Serializer* d) {
auto ptr = reinterpret_cast<const uint8_t*>(object) + f.offset;
return f.type->serialize(d, ptr);
}))
return false;
}
return true;
}
bool Serializer::field(const std::string& name,
const std::function<bool(dap::Serializer*)>& cb) {
Serializer s(&(*json)[name]);

View File

@@ -98,6 +98,8 @@ struct Serializer : public dap::Serializer {
bool serialize(const any& v) override;
bool array(size_t count,
const std::function<bool(dap::Serializer*)>&) override;
bool fields(const void* object,
const std::initializer_list<Field>& fields) override;
bool field(const std::string& name, const FieldSerializer&) override;
void remove() override;
@@ -130,10 +132,6 @@ struct Serializer : public dap::Serializer {
return dap::Serializer::serialize(v);
}
inline bool serialize(const void* o, const std::initializer_list<Field>& f) {
return dap::Serializer::serialize(o, f);
}
inline bool serialize(const char* v) { return dap::Serializer::serialize(v); }
private:

View File

@@ -56,7 +56,9 @@ DAP_STRUCT_TYPEINFO(JSONTestObject,
DAP_FIELD(o2, "o2"),
DAP_FIELD(inner, "inner"));
TEST(JSONSerializer, Decode) {}
struct JSONObjectNoFields {};
DAP_STRUCT_TYPEINFO(JSONObjectNoFields, "json-object-no-fields");
} // namespace dap
@@ -91,3 +93,10 @@ TEST(JSONSerializer, SerializeDeserialize) {
ASSERT_EQ(encoded.o2, decoded.o2);
ASSERT_EQ(encoded.inner.i, decoded.inner.i);
}
TEST(JSONSerializer, SerializeObjectNoFields) {
dap::JSONObjectNoFields obj;
dap::json::Serializer s;
ASSERT_TRUE(s.serialize(obj));
ASSERT_EQ(s.dump(), "{}");
}