summaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
authortmartins <thigm85@gmail.com>2020-06-25 15:15:13 +0200
committertmartins <thigm85@gmail.com>2020-06-25 15:15:13 +0200
commitfd6b49e6c3a396b201fb0505181e840f323970ea (patch)
treea35d81ccf4cf2d05b67812f4e701de8825e1a546 /python
parent2f738a456d43288b033ab69463dbf6d66b1426d5 (diff)
add class for serialization
Diffstat (limited to 'python')
-rw-r--r--python/vespa/vespa/json_serialization.py77
1 files changed, 77 insertions, 0 deletions
diff --git a/python/vespa/vespa/json_serialization.py b/python/vespa/vespa/json_serialization.py
new file mode 100644
index 00000000000..d5f059326e7
--- /dev/null
+++ b/python/vespa/vespa/json_serialization.py
@@ -0,0 +1,77 @@
+import datetime
+import json
+import typing
+
+T = typing.TypeVar("T")
+
+
+class ToJson(object):
+ """
+ Utility mix-in class for serializing an object to JSON. It does not really
+ do any conversion on its own, but forces serialization into a standardized
+ API.
+
+ The serialized class is put into an envelope with some data to make it easier
+ to understand what has happened.
+
+ {
+ "version": 1,
+ "class": "Field",
+ "serialized_at": "2018-10-24T12:55:32+00:00",
+ "data": { ... }
+ }
+
+ * version: This value is hard-coded to 1.
+ * class: The name of the class we serialized. For debugging purposes.
+ * serialized_at: The time we serialized the instance of the class. For debugging purposes.
+ * data: The actual data of the serialized class.
+
+ All serialization is based on converting objects to a `dict` which is then converted
+ to JSON using the standard Python json library.
+ """
+
+ @property
+ def to_dict(self) -> typing.Mapping:
+ raise NotImplementedError
+
+ @property
+ def to_envelope(self) -> typing.Mapping:
+ return {
+ "version": 1,
+ "class": self.__class__.__name__,
+ "serialized_at": datetime.datetime.utcnow().isoformat(),
+ "data": self.to_dict,
+ }
+
+ @property
+ def to_json(self) -> str:
+ mapping = self.to_envelope
+ return json.dumps(mapping)
+
+
+class FromJson(typing.Generic[T]):
+ """
+ A mix-in class for deserializing from JSON to an object that implements this class.
+ All JSON must have the same envelope as ToJson to be able to properly deserialize the
+ contents of the mapping.
+ """
+
+ deserializers: typing.MutableMapping[str, "FromJson"] = {}
+
+ def __init_subclass__(cls, **kwargs):
+ super().__init_subclass__(**kwargs) # type: ignore
+ FromJson.deserializers[cls.__name__] = cls
+
+ @staticmethod
+ def from_json(json_string: str) -> T:
+ mapping = json.loads(json_string)
+ return FromJson.map(mapping)
+
+ @staticmethod
+ def map(mapping: typing.Mapping) -> T:
+ mapping_class = FromJson.deserializers[mapping["class"]]
+ return mapping_class.from_dict(mapping["data"])
+
+ @staticmethod
+ def from_dict(mapping: typing.Mapping) -> T:
+ raise NotImplementedError