JSON反序列化C++

3

我想使用C++将JSON文件反序列化为一个对象(类)。我查看了rapidjson库,并使每个类都有一个反序列化方法,其中根作为参数,因此它可以自行反序列化。它看起来像这样:

void PoliceOfficer::Deserialize(rapidjson::Value& root)
{
if (root.IsObject())
{
    if (root.HasMember("name"))
    {
        if (root["name"].IsString())
        {
            name = root["name"].GetString();
        }
    }

    if (root.HasMember("maxHealth"))
    {
        if (root["maxHealth"].IsNumber())
        {
            maxHealth = (float)root["maxHealth"].GetDouble();
        }
    }

    if (root.HasMember("skills"))
    {
        rapidjson::Value& skills = root["skills"];
        if (skills.IsArray())
        {
            for (rapidjson::SizeType i = 0; i < skills.Size(); i++)
            {
                Skill tempSkill;

                tempSkill.Deserialize(skills[i]);

                m_skills.push_back(tempSkill);
            }
        }
    }
}
}

但这似乎是很多工作。您需要在所有要反序列化自身的类中实现此方法。所以我想知道是否有任何自动执行此操作的方法,例如以下代码行(JSON.NET):

 Movie m = JsonConvert.DeserializeObject<Movie>(json);

所以我不需要为所有类编写反序列化方法。我这样做的方式是唯一的吗?我正在使用rapidjson,但我愿意尝试其他库。
希望问题表述清楚 :)
提前感谢!

C++ 没有内省,因此您不能直接这样做,但是您可以查看 boost hana。 - Jarod42
1
我强烈建议不要将其构建到你的类中。这会使你的类变得混乱,代码也会变得混乱。相反,使用自由函数。此外,你的代码非常冗长;重构它,使每个成员读取只有一行。 - M.M
@Jarod42 和 LightnessRacesinOrbit,是的,我也预料到了 :) - Stefan Dimeski
@MattMcNabb 我完全同意你的观点。这只是一个原型代码,我正在学习rapidjson。 - Stefan Dimeski
也许是在3年后,但对于那些来到这里的人会很有用。http://matus-chochlik.github.io/mirror/doc/html/refltool/example/from_rapidjson.html - Volodymyr B.
@M.M 你的意思是将JSON读取部分与类构建分开吗?你会怎么做呢? - Avi
1个回答

1

要解决您所遇到的问题,可能的解决方案是将所有信息集中在一个函数中,其中您可以将映射结构字段 <---> json/xml/ini 文件中的条目。类似于以下内容:

struct abc_t
{
    int a ;
    string b ;
} ;

void serialize(serializer_t &serializer, abc_t &abc)
{
    serializer.exx(abc.a, "abc") ;
    serializer.exx(abc.b, "b") ;
}

问题在于如何编写这个序列化器。解决方案可以是一个抽象类,如下所示:
class serializer_t
{
public:
    virtual ~serializer_t(void) {}
    virtual void exx(int &value, const char *tag) = 0 ;
    virtual void exx(string &value, const char *tag) = 0 ;
} ;

然后你将有两个派生类,一个实现写入(serializer_writer_t),一个实现读取(serializer_reader_t)。
另一种可能性是静态多态:这意味着将原始的 void serialize(serializer_t &serializer, abc_t &abc) 变为模板函数。如果您有一个复合对象,则需要对每个子对象应用此策略。
请查看 boost.serialization,您将找到有关涉及此任务的所有权衡的深入讨论。

你的解决方案很棒!谢谢!但似乎没有不需要在C++中进行大量工作的解决方案。因此,我认为我要转向C#来处理这个问题,因为它更容易且需要更少的代码。 - Stefan Dimeski
如果您有那种自由度,那么这是最好的选择。 - marom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接