diff --git a/.gitignore b/.gitignore
index a69049f253a0485bf1830dab5848aaf02a3ba371..4a776706c427d9eb694a1bffe990f521cf40064d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,9 @@
 # Ignore all pycache folders everywhere
 __pycache__
 
+/tests/deserializer_matrix/new_deserializer2d.png
+/tests/deserializer_matrix/new_deserializer3d.png
+
 # Don't ignore the following files/folders in the root directory
 !/.gitlab
 !/.vscode
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000000000000000000000000000000000000..b6c5d28bf40fda1cebef358daadc17f4ec868e95
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,16 @@
+{
+    // Use IntelliSense to learn about possible attributes.
+    // Hover to view descriptions of existing attributes.
+    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+    "version": "0.2.0",
+    "configurations": [
+                {
+            "name": "Python: Current File",
+            "type": "python",
+            "request": "launch",
+            "program": "${file}",
+            "console": "integratedTerminal"
+        }
+
+    ]
+}
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ba01a5a57f09090a8035be4816357cea16088b3b..8ccba999bd62567b38762c9f3bd1d4e50518bd5e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -171,13 +171,13 @@ Preferrably write short functions, and [pure functions](https://realpython.com/p
 
 ### Running tests
 The tests compare JSON files created after a contribution to the ones before. Any differences will be marked as errors.
-If a model change is part of the contribution the specification needs to be updated under [specification](./doc/static/specification).
-To update the test JSON comparison files run:
+If a model change or deserilizer change is part of the contribution many test files need to be updated.
+This can be automatically done creating three kinds of files:
 
 ```cmd
 pytest tests --update-tests=confirm
 ```
 
-This creates the JSON files for the new model inside the tests_updated folder.
-Manual testing for the new files is required as there is no true comparison to validate them. After that, one can replace the contents of [tests](./tests) with the ones of tests_updated.
-It will also create an updated scheme inside [specification](./doc/static/specification). This will need to be renamed according to the current version of PlotSerializer to be pushed.
\ No newline at end of file
+The first type of files created being all the tests accomodating the new model under the tests_updated folder. They have to be manually checked for correctness and then moved into the initial [plots](./tests/plots) folder.
+The second being the new model under [specification](./doc/static/specification) where it will have to be renamed according to the current version of PlotSerializer to be pushed.
+The third being pictures of every plottype deserialized into a figure to broadly confirm the deserializer is still functioning. Once again the contents must me renamed and replace the old files in [folder](./tests/deserializer_matrix) upon confirming correctness.
diff --git a/plot_serializer/matplotlib/deserializer.py b/plot_serializer/matplotlib/deserializer.py
index ad9a23541dfc25a74f4092c1b48c70a2f92552da..21739d69c6556481667f332848c3e72cadd223cf 100644
--- a/plot_serializer/matplotlib/deserializer.py
+++ b/plot_serializer/matplotlib/deserializer.py
@@ -1,4 +1,4 @@
-from typing import Any
+from typing import Any, Optional
 
 import matplotlib.pyplot as plt
 import numpy as np
@@ -21,22 +21,26 @@ from plot_serializer.model import (
     ScatterTrace3D,
     SurfaceTrace3D,
 )
+from plot_serializer.proxy import Proxy
 
 
-def deserialize_from_json_file(filename: str) -> MplFigure:
+def deserialize_from_json_file(filename: str, fig: Any = None, ax: Any = None) -> Optional[MplFigure]:
     with open(filename, "r") as file:
-        return deserialize_from_json(file.read())
+        return deserialize_from_json(file.read(), fig=fig, ax=ax)
 
 
-def deserialize_from_json(json: str) -> MplFigure:
+def deserialize_from_json(json: str, fig: Optional[MplFigure] = None, ax: Any = None) -> Optional[MplFigure]:
     model_figure = Figure.model_validate_json(json_data=json)
-
-    if model_figure.plots[0].type == "3d":
-        fig, ax = plt.subplots(len(model_figure.plots), subplot_kw={"projection": "3d"})
-    else:
-        fig, ax = plt.subplots(len(model_figure.plots))
-    if model_figure.title is not None:
-        fig.suptitle(model_figure.title)
+    if isinstance(ax, Proxy):
+        ax = ax.delegate
+    if ax is None:
+        if model_figure.plots[0].type == "3d":
+            fig, ax = plt.subplots(len(model_figure.plots), subplot_kw={"projection": "3d"})
+        else:
+            fig, ax = plt.subplots(len(model_figure.plots))
+    if fig is not None:
+        if model_figure.title is not None:
+            fig.suptitle(model_figure.title)
 
     i = 0
     for plot in model_figure.plots:
@@ -307,13 +311,13 @@ def _deserialize_linetrace3d(trace: LineTrace3D, ax: MplAxes3D) -> None:
 
 
 def _deserialize_surfacetrace3d(trace: SurfaceTrace3D, ax: MplAxes3D) -> None:
-    x = np.zeros([trace._length, trace._width])
-    y = np.zeros([trace._length, trace._width])
-    z = np.zeros([trace._length, trace._width])
+    x = np.zeros([trace.length, trace.width])
+    y = np.zeros([trace.length, trace.width])
+    z = np.zeros([trace.length, trace.width])
     i = 0
     j = 0
     for point in trace.datapoints:
-        if j == trace._width:
+        if j == trace.width:
             j = 0
             i = i + 1
         x[i][j] = point.x
@@ -337,10 +341,13 @@ def _deserialize_pieplot(plot: PiePlot, ax: MplAxes) -> None:
 
     # We need to ignore the argument types here, because matplotlib says
     # it doesn't support None inside of the lists, but it actually does.
-    ax.pie(
-        x,
-        labels=label,  # type: ignore[arg-type]
-        colors=color,  # type: ignore[arg-type]
-        explode=explode,  # type: ignore[arg-type]
-        radius=plot.radius,  # type: ignore[arg-type]
-    )
+    if plot.radius is None:
+        plot.radius = 1
+    else:
+        ax.pie(
+            x,
+            labels=label,  # type: ignore[arg-type]
+            colors=color,  # type: ignore[arg-type]
+            explode=explode,  # type: ignore[arg-type]
+            radius=plot.radius,
+        )
diff --git a/plot_serializer/matplotlib/serializer.py b/plot_serializer/matplotlib/serializer.py
index c68af47d624e8f09eb63e54e02fd1187ed528bc4..5af88b57c5701520972f0893e47c7c9cb7996c3a 100644
--- a/plot_serializer/matplotlib/serializer.py
+++ b/plot_serializer/matplotlib/serializer.py
@@ -101,14 +101,6 @@ PLOTTING_METHODS = [
 ]
 
 
-def is_array_like(x):
-    try:
-        np.array(x)
-        return True
-    except Exception:
-        return False
-
-
 def _convert_matplotlib_color(
     self, color_list: Any, length: int, cmap: Any, norm: Any
 ) -> Tuple[List[str] | None, bool]:
@@ -274,6 +266,19 @@ class _AxesProxy(Proxy[MplAxes]):
 
         return result
 
+    """
+    Custom wrapper for ax.plot with additional functionality.
+
+    {plt.Axes.plot.__doc__}
+
+    Parameters
+    ----------
+    *args : tuple
+        Positional arguments passed to `ax.plot`.
+    **kwargs : dict
+        Keyword arguments passed to `ax.plot`.
+    """
+
     def plot(self, *args: Any, **kwargs: Any) -> list[Line2D]:
         try:
             mpl_lines = self.delegate.plot(*args, **kwargs)
@@ -844,8 +849,8 @@ class _AxesProxy3D(Proxy[MplAxes3D]):
             traces.append(
                 SurfaceTrace3D(
                     type="surface3D",
-                    _length=length,
-                    _width=width,
+                    length=length,
+                    width=width,
                     label=label,
                     datapoints=datapoints,
                 )
diff --git a/plot_serializer/model.py b/plot_serializer/model.py
index a8c9e61dae45a4fe759df12795af49fa797d2459..fd6575d33cd765ef896dad37726dbc7262f40571 100644
--- a/plot_serializer/model.py
+++ b/plot_serializer/model.py
@@ -13,8 +13,7 @@ from pydantic import BaseModel, ConfigDict, Field, model_validator
 
 Scale = Union[ScaleBase, str]
 
-MetadataValue = Union[int, float, str]
-Metadata = Dict[str, MetadataValue]
+Metadata = Dict[Any, Any]
 
 Color = Optional[str | Tuple[float, float, float] | Tuple[float, float, float, float]]
 
@@ -254,15 +253,11 @@ class LineTrace3D(BaseModel):
 class SurfaceTrace3D(BaseModel):
     type: Literal["surface3D"]
     metadata: Metadata = {}
-    _length: int
-    _width: int
+    length: int
+    width: int
     label: Optional[str] = None
     datapoints: List[Point3D]
 
-    @model_validator(mode="after")
-    def check_dimension_matches_dataponts(self) -> "SurfaceTrace3D":
-        return self
-
     def emit_warnings(self) -> None:
         msg: List[str] = []
 
@@ -272,6 +267,10 @@ class SurfaceTrace3D(BaseModel):
         if len(msg) > 0:
             logging.warning("%s is not set for SurfaceTrace3D.", msg)
 
+    @model_validator(mode="after")
+    def check_dimension_matches_dataponts(self) -> "SurfaceTrace3D":
+        return self
+
     @model_validator(mode="before")
     def cast_numpy_types(cls: Any, values: Any) -> Any:  # noqa: N805  # noqa: N805
         def convert(value: Any) -> Any:
diff --git a/requirements.txt b/requirements.txt
index ae88b3ffa3b360c9073b55f7e6ffcca0d3e78d87..b5494a836a76085ae4e9a99742d57c33e08a6512 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -22,3 +22,6 @@ types-docutils
 
 # Unit testing
 pytest
+
+#Debug
+debugpy
\ No newline at end of file
diff --git a/tests/deserializer_matrix/deserializer2d.png b/tests/deserializer_matrix/deserializer2d.png
new file mode 100644
index 0000000000000000000000000000000000000000..c1024aa633a4436b8351635019fd93264692a3ef
Binary files /dev/null and b/tests/deserializer_matrix/deserializer2d.png differ
diff --git a/tests/deserializer_matrix/deserializer3d.png b/tests/deserializer_matrix/deserializer3d.png
new file mode 100644
index 0000000000000000000000000000000000000000..e5e8873e6907646a32b5ce3f23186200fbd286e9
Binary files /dev/null and b/tests/deserializer_matrix/deserializer3d.png differ
diff --git a/tests/plots/surface_plot3D_all_features.json b/tests/plots/surface_plot3D_all_features.json
index ddf7aaa1e312e8f92a970517c516905f33bbf4dd..3f4f2ff2aa07ac76f21e73638063f3ab8a939a76 100644
--- a/tests/plots/surface_plot3D_all_features.json
+++ b/tests/plots/surface_plot3D_all_features.json
@@ -18,6 +18,8 @@
       "traces": [
         {
           "type": "surface3D",
+          "length": 20,
+          "width": 20,
           "label": "testSurface",
           "datapoints": [
             {
diff --git a/tests/plots/surface_plot3D_simple.json b/tests/plots/surface_plot3D_simple.json
index 4437a6e02fd984d5721956887d5a88512778ad7a..960ad28dd4d5e6096bbfdc328b56335e67a9fb35 100644
--- a/tests/plots/surface_plot3D_simple.json
+++ b/tests/plots/surface_plot3D_simple.json
@@ -18,6 +18,8 @@
       "traces": [
         {
           "type": "surface3D",
+          "length": 8,
+          "width": 8,
           "label": "_child0",
           "datapoints": [
             {
diff --git a/tests/plots/surface_plot3D_test_metadata.json b/tests/plots/surface_plot3D_test_metadata.json
index c6c0391896548772b0be23f7672e5497785df3c1..1e1fa1655c9a67a6a24ebd8a7052de97db7c5383 100644
--- a/tests/plots/surface_plot3D_test_metadata.json
+++ b/tests/plots/surface_plot3D_test_metadata.json
@@ -27,6 +27,8 @@
       "traces": [
         {
           "type": "surface3D",
+          "length": 8,
+          "width": 8,
           "label": "_child0",
           "datapoints": [
             {
@@ -362,6 +364,8 @@
           "metadata": {
             "key": "value"
           },
+          "length": 8,
+          "width": 8,
           "label": "_child1",
           "datapoints": [
             {
diff --git a/tests/test_deserializer.py b/tests/test_deserializer.py
new file mode 100644
index 0000000000000000000000000000000000000000..3248c18d323601d8cbd02401003f8d4c5cfc4bfc
--- /dev/null
+++ b/tests/test_deserializer.py
@@ -0,0 +1,58 @@
+from typing import Any
+
+from matplotlib import pyplot as plt
+
+from plot_serializer.matplotlib.deserializer import deserialize_from_json_file
+from plot_serializer.matplotlib.serializer import MatplotlibSerializer
+
+files = [
+    "./tests/plots/bar_plot_all_features.json",
+    "./tests/plots/box_plot_all_features.json",
+    "./tests/plots/errorbar_all_features.json",
+    "./tests/plots/hist_plot_all_features_datasets.json",
+    "./tests/plots/line_plot_all_features.json",
+    "./tests/plots/pie_plot_all_features.json",
+    "./tests/plots/scatter_plot_all_enabled.json",
+]
+
+files3d = [
+    "./tests/plots/line_plot3D_all_features.json",
+    "./tests/plots/scatter3D_plot_marker.json",
+    "./tests/plots/surface_plot3D_all_features.json",
+]
+
+
+def test_deserializer(request: Any) -> None:
+    rows, columns = 3, 3
+
+    update_tests = request.config.getoption("--update-tests")
+
+    serializer = MatplotlibSerializer()
+    fig, ax = serializer.subplots(rows, columns, figsize=(15, 10))
+    fig.suptitle("Amount of plots: " + str(len(files)))
+
+    for i in range(len(files)):
+        deserialize_from_json_file(files[i], ax=ax[i // columns, i % columns])
+
+    if update_tests == "confirm":
+        fig.savefig("./tests/deserializer_matrix/new_deserializer2d.png")
+
+    plt.close()
+
+
+def test_deserializer3d(request: Any) -> None:
+    rows, columns = 2, 2
+
+    update_tests = request.config.getoption("--update-tests")
+
+    serializer = MatplotlibSerializer()
+    fig, ax = serializer.subplots(rows, columns, figsize=(15, 10), subplot_kw={"projection": "3d"})
+    fig.suptitle("Amount of plots: " + str(len(files3d)))
+
+    for i in range(len(files3d)):
+        deserialize_from_json_file(files3d[i], ax=ax[i // columns, i % columns])
+
+    if update_tests == "confirm":
+        fig.savefig("./tests/deserializer_matrix/new_deserializer3d.png")
+
+    plt.close()