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 do I parse custom type inheriting from vector? #115

Closed
henriksjostrom opened this issue Apr 25, 2017 · 7 comments
Closed

How do I parse custom type inheriting from vector? #115

henriksjostrom opened this issue Apr 25, 2017 · 7 comments

Comments

@henriksjostrom
Copy link

I have a custom type inheriting from vector and unfortunately I'm getting the compiling error "more than one partial specialization matches the template argument list".

How do I resolve that conflict?

Code example:

#include <jsoncons/json.hpp>
#include <vector>

struct own_vector : std::vector<int64_t> { using  std::vector<int64_t>::vector; };

namespace jsoncons {
template<class Json>
struct json_type_traits<Json, own_vector> {
	static bool is(const Json& rhs) noexcept{return true;}
	static own_vector as(const Json& rhs){return own_vector();}
	static Json to_json(const own_vector& val){return Json();}
};
};
int main(int argc, char **argv) {
	jsoncons::json j = own_vector();
}
@danielaparker
Copy link
Owner

danielaparker commented Apr 25, 2017

You don't need a json_type_traits specialization of own_vector. As long as your own_vector class satisfies the C++ SequenceContainer concept, which it does by virtue of inheriting from std::vector, it's already supported.

struct own_vector : std::vector<int64_t> 
{ 
    own_vector(std::initializer_list<int64_t> init)
        : std::vector<int64_t>(init){}
    using  std::vector<int64_t>::vector; 
};

int main(int argc, char **argv) {
    jsoncons::json j = own_vector({1,2,3});

    std::cout << "(1) " << j << std::endl;

    own_vector v = j.as<own_vector>();
    std::cout << "(2) ";
    for (auto val : v)
    {
        std::cout << val << " ";
    }
    std::cout << std::endl;
}

produces

(1) [1,2,3]
(2) 1 2 3

@henriksjostrom
Copy link
Author

Unfortunately I still do as my encoding to json is not represented as a json vector but as a json object containing a vector. Not shown in the example.

Any way of circumventing that without moving the vector to just be a member of own_vector?

@danielaparker
Copy link
Owner

I don't see how that would make any difference, if I understand you correctly. For example,

int main(int argc, char **argv) {
    jsoncons::json j;
    
    j["v"] = own_vector({ 1,2,3 });

    std::cout << "(1) " << j << std::endl;
}

produces the expected

(1) {"v":[1,2,3]}

Could you show a complete example?

Thanks,
Daniel

@henriksjostrom
Copy link
Author

Certainly.

In my actual usecase I have a more complex inner class where all elements share some attributes which I break out and put in the top level. As representing that here would get unnecessarily messy here is a nonstandard conversion of the vector:

#include <jsoncons/json.hpp>
#include <vector>
#include <string>

//own vector will always be of an even length 
struct own_vector : std::vector<int64_t> { using  std::vector<int64_t>::vector; };

namespace jsoncons {
template<class Json>
struct json_type_traits<Json, own_vector> {
	static bool is(const Json& rhs) noexcept{return true;}
	static own_vector as(const Json& rhs){return own_vector();}
	static Json to_json(const own_vector& val){
		Json j;
		for(uint64_t i=0;i<val.size();i+2){
			j[std::to_string(val[i])] = val[i + 1];
		}
		return j;
	}
};
};
int main(int argc, char **argv) {
	jsoncons::json j = own_vector({0,9,8,7});
	std::cout << j;
}

this should end up as {"0":9,"8":7}

@danielaparker
Copy link
Owner

Oh I see. I would suggest using a helper class for that, e.g.

struct own_vector_helper
{
    own_vector v_;

    own_vector_helper(own_vector v) : v_(v) {}

    template <class Json>
    Json to_json() const
    {
        Json j;
        for (uint64_t i = 0; i+1 < v_.size(); i += 2) {
            j[std::to_string(v_[i])] = v_[i + 1];
        }
        return j;
    }
};

namespace jsoncons {
template<class Json>
struct json_type_traits<Json, own_vector_helper> {
    static Json to_json(const own_vector_helper& val) {
        return val.to_json<Json>();
    }
};
};
int main(int argc, char **argv) {
    jsoncons::json j = own_vector_helper(own_vector({ 0,9,8,7 }));
    std::cout << j;
}

Output:

{"0":9,"8":7}

@henriksjostrom
Copy link
Author

Ah, that is a resonable way of working around the problem. Thank you for your assistance

@danielaparker
Copy link
Owner

This is a duplicate of #133. This issue has been addressed on 2018-12-21 master, see the last example in json_type_traits

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