Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to override default string serialization? #2079

Closed
jkwill87 opened this issue May 1, 2020 · 2 comments
Closed

How to override default string serialization? #2079

jkwill87 opened this issue May 1, 2020 · 2 comments

Comments

@jkwill87
Copy link

jkwill87 commented May 1, 2020

Describe what you want to achieve

I would like to be able to override the default string serialization to return a null value for empty strings. For instance,

source

nlohmann::json j;
j["name"] = ""
std::cout << j << std::endl;

output

{"name": null}

Describe what you tried

  1. Overriding void to_json(nlohmann::json &j, const std::string &s). Redefinition error while linking.
  2. Writing a custom serializer as done in the test files. Doesn't enter overwritten to_json, for example,

source

template<typename T, typename = void>
struct custom_serializer {
    // defaults
    template <typename BasicJsonType, typename U = T>
    static void from_json(const BasicJsonType &j, U &t) {
        using nlohmann::from_json;
        from_json(j, t);
    }
    template <typename BasicJsonType, typename U = T>
    static void to_json(BasicJsonType &j, const U &t) {
        using nlohmann::to_json;
        to_json(j, t);
    }
    // strings
    template <typename BasicJsonType>
    static void from_json(const BasicJsonType &j, std::string &t) {
        using nlohmann::to_json;
        to_json(t,j);
    }
    template <typename BasicJsonType>
    static void to_json(BasicJsonType &j, const std::string &t) {
        if (t.empty()) j = nullptr;
        else j = t;
    }
};

using custom_json = nlohmann::basic_json<
    std::map,
    std::vector,
    std::string,
    bool,
    std::int64_t,
    std::uint64_t,
    double,
    std::allocator,
    custom_serializer
>;

custom_json j;
j["name"] = "";

output

{"name": ""}

I'm working on my first CPP project and admittedly inexperienced templating or concepts like SFINAE. If anyone has a possible solution or point out where I'm going wrong it would appreciated. Thank you!

Describe which system (OS, compiler) you are using

Linux 5.6.6 x86-64, clang 10.0.0

Describe which version of the library you are using (release version, develop branch)

develop branch

@nlohmann
Copy link
Owner

nlohmann commented May 2, 2020

No, this is currently not possible without changing the code of the original serializer, see include/nlohmann/detail/output/serializer.hpp, function dump_escaped.

@jkwill87
Copy link
Author

jkwill87 commented May 2, 2020

Alright, thank you. I was able to make this change in the following to serializer::dump

switch (val.m_type) {

    // ...

    case value_t::string: {
        if ((*val.m_value.string).empty()) {
            o->write_characters("null", 4);
        } else {
            o->write_character('\"');
            dump_escaped(*val.m_value.string, ensure_ascii);
            o->write_character('\"');
        }
        return;
    }

    // ...

@jkwill87 jkwill87 closed this as completed May 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants