Loki-Astari / ThorsSerializer

C++ Serialization library for JSON

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Redefine traits at runtime

ripe909 opened this issue · comments

I don't think this is possible at present (?)

I have some object types that need to change what traits are serialized based on user input (at runtime).

Currently I have a compile time #define that switches the traits macro, but I need to change this to be a runtime setting.

#if defined TRAIT_OPTION_1
ThorsAnvil_MakeTrait(TEST_OBJECT, _children, _name);
#else
ThorsAnvil_MakeTrait(TEST_OBJECT, _name);
#endif

Hi there.

There is a way to conditionally serialize members.

struct TEST_OBJECT
{
    std::map<std::string, bool>   filter;   // filter object
    std::string _children;
    std::string _name;
};

ThorsAnvil_MakeFilter(TEST_OBJECT, filter);                     // define a filter object
ThorsAnvil_MakeTrait(TEST_OBJECT, _children, _name); // define a filter.

If the name of the field is in the filter AND has a value false then it will not be serialized on ouptut.
Otherwise the value is serialized.

Note: This only affects output and the filter is not used on input.

hmm, interesting! I didn't see this in the docs, so I assume it is a new capability?

I see the test case for it, which is a good example: https://github.com/Loki-Astari/ThorsSerializer/blob/dac66aa1feefd3559032d9df3178ec19c318caf4/src/Serialize/test/FilterValuesTest.cpp

I have a fairly large tree of objects, which would require updating thousands of instances to remove/add a member to the filter, and it would increase the memory footprint to store the filter map.

Since I need a global Trait filter (not per object instance), I may need to figure out a different method.

Yes. I am working on DB driver with optional field requirements.
This has made me add this feature.

Once I have stabalized the DB driver I will add the appropriate documentation to the Serializer product.

Sounds good. I am using your library to serialize data from a microcontroller's SDRAM to an SD card, so memory is a scarce resource.

Note: The filter does not have to be std::map<std::string, bool> object.

It can be an object that supports bool operator[](std::string).
It should be relatively simple to add an object that accesses a global structure.

std::map<std::string, bool>   globalFilter;

class GlobalFilter
{
     std::string prefix;
    public:
        GlobalFilter(std::string const& prefix): prefix(prefix) {}
        bool operator[](std::string const& name) const
        {
                return globalFilter[prefix + ":" + name];
        }
};

Then it each object just add a member to the type.
        GlobalFilter   filter("ObjectName");  // You could potentially make this static to save space
                                                                     // Though this adds some of its own complexities.

I was able to try this today and it worked perfectly. I used a static member of my objects as a "global" filter