changeset 51:3dc37a5af1b1

new method PythonObject::ConvertToJson()
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 09 Dec 2020 16:34:03 +0100
parents 70abe3ebbbfc
children 13eb87c58b0a
files Sources/PythonObject.cpp Sources/PythonObject.h
diffstat 2 files changed, 126 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/Sources/PythonObject.cpp	Tue Dec 08 19:02:30 2020 +0100
+++ b/Sources/PythonObject.cpp	Wed Dec 09 16:34:03 2020 +0100
@@ -65,11 +65,14 @@
 }
 
 
-bool PythonObject::ToUtf8String(std::string& target)
+bool PythonObject::ToUtf8String(std::string& target,
+                                PyObject* value)
 {
-  PyObject* value = GetPyObject();  // Raises an exception if needed
-
-  if (PyUnicode_Check(value))
+  if (value == NULL)
+  {
+    ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer);
+  }
+  else if (PyUnicode_Check(value))
   {
     PythonObject encoded(lock_, PyUnicode_AsEncodedString(value, "utf-8", "replace"));
     if (encoded.IsValid())
@@ -132,3 +135,105 @@
   }
 }
 
+
+void PythonObject::ConvertToJson(Json::Value& target,
+                                 PyObject* source)
+{
+  // WARNING: The order *is* important!
+  if (source == Py_None)
+  {
+    target = Json::nullValue;
+  }
+  else if (PyBool_Check(source))
+  {
+    target = (PyObject_IsTrue(source) ? true : false);
+  }
+  else if (PyLong_Check(source))
+  {
+    target = static_cast<int32_t>(PyLong_AsLong(source));
+  }
+  else if (PyFloat_Check(source))
+  {
+    target = PyFloat_AsDouble(source);
+  }
+  else if (PyNumber_Check(source))
+  {
+    PythonObject asLong(lock_, PyNumber_Long(source));
+    if (PyLong_Check(asLong.GetPyObject()))
+    {
+      target = static_cast<int32_t>(PyLong_AsLong(asLong.GetPyObject()));
+    }
+    else
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
+    }
+  }
+  else if (PyUnicode_Check(source))
+  {
+    std::string s;
+    if (ToUtf8String(s, source))
+    {
+      target = s;
+    }
+    else
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(NotImplemented);
+    }
+  }
+#if PY_MAJOR_VERSION == 2
+  else if (PyString_Check(source))
+  {
+    target = PyString_AS_STRING(source);
+  }
+#endif
+  else if (PySequence_Check(source))  // tuples or lists
+  {
+    Py_ssize_t size = PySequence_Size(source);
+
+    if (size < 0)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);      
+    }
+
+    target = Json::arrayValue;
+    for (Py_ssize_t i = 0; i < size; i++)
+    {
+      Json::Value item;
+      ConvertToJson(item, PySequence_GetItem(source, i));
+      target.append(item);
+    }
+  }
+  else if (PyMapping_Check(source))  // dictionaries
+  {
+    PythonObject items(lock_, PyMapping_Items(source));
+
+    Py_ssize_t size = PySequence_Size(items.GetPyObject());
+
+    if (size < 0)
+    {
+      ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);      
+    }
+
+    for (Py_ssize_t i = 0; i < size; i++)
+    {
+      PyObject* pair = PySequence_GetItem(items.GetPyObject(), i);
+
+      std::string key;
+      Json::Value value;
+      if (pair != NULL &&
+          ToUtf8String(key, PySequence_GetItem(pair, 0)))
+      {
+        ConvertToJson(value, PySequence_GetItem(pair, 1));
+        target[key] = value;
+      }
+      else
+      {
+        ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);      
+      }
+    }
+  }
+  else
+  {
+    ORTHANC_PLUGINS_THROW_EXCEPTION(NotImplemented);
+  }
+}
--- a/Sources/PythonObject.h	Tue Dec 08 19:02:30 2020 +0100
+++ b/Sources/PythonObject.h	Wed Dec 09 16:34:03 2020 +0100
@@ -21,6 +21,8 @@
 
 #include "PythonLock.h"
 
+#include <json/value.h>
+
 class PythonObject : public boost::noncopyable
 {
 private:
@@ -28,6 +30,12 @@
   PyObject    *object_;
   bool         borrowed_;
 
+  bool ToUtf8String(std::string& target,
+                    PyObject* value);
+
+  void ConvertToJson(Json::Value& target,
+                     PyObject* source);
+  
 public:
   PythonObject(PythonLock& lock,
                PyObject *object,
@@ -44,9 +52,17 @@
 
   PythonObject* GetAttribute(const std::string& name);
 
-  bool ToUtf8String(std::string& target);
+  bool ToUtf8String(std::string& target)
+  {
+    return ToUtf8String(target, GetPyObject());
+  }
 
   void Format(std::ostream& os);
 
   PyObject* Release();
+
+  void ConvertToJson(Json::Value& target)
+  {
+    ConvertToJson(target, GetPyObject());
+  }
 };