|  | 
| 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