|
9 | 9 | #ifndef PYBIND11_JSON_HPP |
10 | 10 | #define PYBIND11_JSON_HPP |
11 | 11 |
|
| 12 | +#include <set> |
12 | 13 | #include <string> |
13 | 14 | #include <vector> |
14 | 15 |
|
@@ -67,7 +68,7 @@ namespace pyjson |
67 | 68 | } |
68 | 69 | } |
69 | 70 |
|
70 | | - inline nl::json to_json(const py::handle& obj) |
| 71 | + inline nl::json to_json(const py::handle& obj, std::set<const PyObject*>& refs) |
71 | 72 | { |
72 | 73 | if (obj.ptr() == nullptr || obj.is_none()) |
73 | 74 | { |
@@ -118,24 +119,48 @@ namespace pyjson |
118 | 119 | } |
119 | 120 | if (py::isinstance<py::tuple>(obj) || py::isinstance<py::list>(obj)) |
120 | 121 | { |
| 122 | + auto insert_ret = refs.insert(obj.ptr()); |
| 123 | + if (!insert_ret.second) { |
| 124 | + throw std::runtime_error("Circular reference detected"); |
| 125 | + } |
| 126 | + |
121 | 127 | auto out = nl::json::array(); |
122 | 128 | for (const py::handle value : obj) |
123 | 129 | { |
124 | | - out.push_back(to_json(value)); |
| 130 | + out.push_back(to_json(value, refs)); |
125 | 131 | } |
| 132 | + |
| 133 | + refs.erase(insert_ret.first); |
| 134 | + |
126 | 135 | return out; |
127 | 136 | } |
128 | 137 | if (py::isinstance<py::dict>(obj)) |
129 | 138 | { |
| 139 | + auto insert_ret = refs.insert(obj.ptr()); |
| 140 | + if (!insert_ret.second) { |
| 141 | + throw std::runtime_error("Circular reference detected"); |
| 142 | + } |
| 143 | + |
130 | 144 | auto out = nl::json::object(); |
131 | 145 | for (const py::handle key : obj) |
132 | 146 | { |
133 | | - out[py::str(key).cast<std::string>()] = to_json(obj[key]); |
| 147 | + out[py::str(key).cast<std::string>()] = to_json(obj[key], refs); |
134 | 148 | } |
| 149 | + |
| 150 | + refs.erase(insert_ret.first); |
| 151 | + |
135 | 152 | return out; |
136 | 153 | } |
| 154 | + |
137 | 155 | throw std::runtime_error("to_json not implemented for this type of object: " + py::repr(obj).cast<std::string>()); |
138 | 156 | } |
| 157 | + |
| 158 | + inline nl::json to_json(const py::handle& obj) |
| 159 | + { |
| 160 | + std::set<const PyObject*> refs; |
| 161 | + return to_json(obj, refs); |
| 162 | + } |
| 163 | + |
139 | 164 | } |
140 | 165 |
|
141 | 166 | // nlohmann_json serializers |
|
0 commit comments