Skip to content

Serialization to JSON#

TracingNode can be serialized into JSON via [to_dict] method:

from nicetrace import trace

with trace("my node", inputs={"x": 42}) as node:
    node.add_outputs("y", "my_result")

Calling node.to_dict() returns:

{
  "name": "my node",
  "uid": "li7znrGkQr",
  "entries": [
    {
      "kind": "input",
      "value": 42,
      "name": "x"
    },
    {
      "kind": "output",
      "value": "my_result",
      "name": "y"
    }
  ],
  "start_time": "2024-07-08T16:26:48.619336",
  "end_time": "2024-07-08T16:26:48.619346",
  "version": "4"
}

When inputs or a result are not directly serializable into JSON options are provided:

Serialization of dataclasses#

Dataclasses are serialized as dict:

from dataclasses import dataclass
from nicetrace import trace, with_trace


@dataclass
class Person:
    name: str
    age: int


@with_trace
def say_hi(person):
    return f"Hi {person.name}!"


with trace("root") as c:
    person = Person("Alice", 21)
    say_hi(person)

creates the following JSON description of the node:

{
  "name": "root",
  "uid": "KhwWyfyqGX",
  "children": [
    {
      "name": "say_hi",
      "uid": "3cFmee7Oq7",
      "kind": "call",
      "entries": [
        {
          "kind": "input",
          "value": {
            "name": "Alice",      # <<<<<<<
            "age": 21,            # <<<<<<<
            "_type": "Person"     # <<<<<<<
          },
          "name": "person"
        },
        {
          "kind": "output",
          "value": "Hi Alice!"
        }
      ],
      "start_time": "2024-07-08T16:28:44.392553",
      "end_time": "2024-07-08T16:28:44.392573"
    }
  ],
  "start_time": "2024-07-08T16:28:44.392522",
  "end_time": "2024-07-08T16:28:44.392577",
  "version": "4"
}

Method __trace_to_node__#

A user type may define method __trace_to_node__ to provide a custom serializer.

class Person:
    name: str
    age: int

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __trace_to_node__(self):
        return {"name": self.name, "age": self.age}

person = Person("Peter", 24)

When person is serialized, the following dictionary is produced:

{
    "name": "Peter",
    "age": 24,
    "_type": "Person"
}

Registration of serializer#

Sometimes we do not or we cannot modify a class. Registration a serializer for a given type is there for this purpose.

from nicetrace import register_custom_serializer


class MyClass:
    def __init__(self, x):
        self.x = x


def myclass_serializer(m: MyClass):
    return {"x": m.x}


register_custom_serializer(MyClass, myclass_serializer)

Fallback#

When no mechanism above is used then only name of the type and object id is serialized.

E.g.:

{
    "_type": "Person",
    "id": 140263930622832
}