Я пытался понять это сейчас, и, может быть, я просто слишком долго смотрел на него?
Во всяком случае проблема заключается в том, чтобы найти хороший способ представления JSON в С++ и, прежде чем вы прочтете больше, обратите внимание, что меня не интересуют библиотеки, способные на это, поэтому я хочу сделать это в raw C или С++ (С++ 11 в порядке), нет boost, no libjson, я знаю о них и по причинам, выходящим за рамки этого вопроса, я не могу (/wont) добавлять зависимости.
Теперь, когда это прояснилось, позвольте мне рассказать вам немного о проблеме и о том, что я пробовал до сих пор.
Проблема заключается в том, чтобы найти хороший способ представления JSON в С++, причина, по которой это немного проблематично, заключается в том, что JSON является супер-слабо типизированным, а С++ действительно жестко типизирован. рассмотрите JSON на секунду, что такое JSON, действительно способный типично?
- Число (например,
42
или3.1415
) - Строка (например,
"my string"
) - Массив (например,
[]
или[1,3.1415,"my string]
) - Объект (например,
{}
или{42, 3.1415, "my string", [], [1,3.1415, "my string]}
Итак, это означает, что существуют два "необработанных" типа: Число и Строка, а два типа контейнеров Массив и Объект. Необработанные типы довольно прямолинейны, в то время как типы контейнеров становятся сложными на C/С++, поскольку они могут и, вероятно, будут содержать элементы разных типов, поэтому любой встроенный тип на языке не будет достаточным, как есть, массив не может содержать элементы разных типов. Это справедливо и для STL-типов (список, вектор, массив и т.д.) (Если они не имеют полиморфного равенства).
Таким образом, любой контейнер в JSON может содержать любой тип json-типа, который в значительной степени подходит для него.
Что я прототипировал или пытался и почему это не работает Моя первая наивная мысль заключалась в том, чтобы просто использовать шаблоны, поэтому я настроил тип json-object или json- node, который затем использовал бы шаблоны, чтобы решить, что в нем, поэтому у него будет структура вроде этого:
template <class T>
class JSONNode {
const char *key;
T value;
}
Хотя это казалось многообещающим, однако, когда я начал работать с ним, я понял, что столкнулся с проблемами, когда пытался упорядочить узлы в виде контейнера (например, array, vector, unordered_map и т.д.), поскольку они все еще хотите знать тип этого JSONNode! если один node определяется как JSONNode<int>
, а другой - JSONNode<float>
ну, тогда будет проблематично иметь их в контейнере.
Итак, я продвигаюсь мимо этого, я все равно не заинтересован в том, чтобы держать их в контейнере, я был бы счастлив сделать их самосознающими или как их называть, т.е. объявление в указателе на следующий node, но опять-таки становится сложно определить тип node, и примерно здесь, когда я начинаю думать о полиморфизме.
Полиморфизм
Позвольте просто создать виртуальный JSONNode
и реализовать типы JSONNumberNode, JSONStringNode, JSONArrayNode
и JSONObjectNode
, и они будут хорошо вписываться в любой контейнер, в котором я мог бы их использовать, используя полиморфизм, чтобы позволить им быть JSONNodes.
Пример кода может быть на месте.
class JSONNode {
public:
const char *key;
//?? typed value, can't set a type
};
class JSONNumberNode : public JSONNode {
public:
int value;
}
class JSONStringNode : public JSONNode {
public:
const char *value;
}
Сначала я думал, что это путь. Однако, когда я начал думать о том, как обрабатывать элемент value, я понял, что не могу получить доступ к значению, даже если я написал определенную функцию для получения значения, что бы он вернулся?
Таким образом, я уверен, что у меня есть объекты с разными типизированными значениями, но я не могу получить к ним доступ без первого приведения к правильному типу, поэтому я мог бы сделать dynamic_cast<JSONStringNode>(some_node);
, но как бы я знал, к чему это можно привести? RTTI? Ну, я чувствую, что в этот момент мне становится сложнее, я думаю, я мог бы использовать typeof или decltype, выясняя, что придумать, но не удалось.
Типы POD
Поэтому я попробовал что-то другое, я подумал, что могу утверждать, что, возможно, я мог бы сделать это в корме. Затем я установил бы часть value
как void *
и попробовал бы некоторые union
отслеживать типы. Однако я получаю ту же проблему, что и у меня, а именно, как передавать данные в типы.
Я чувствую необходимость обернуть этот вопрос, почему я не углубился в то, что я пытался использовать POD..
Итак, если у кого-то есть умное решение о том, как представлять JSON в С++, учитывая эту информацию, я был бы так благодарен.