{"id":23032253,"url":"https://github.com/i2mint/py2json","last_synced_at":"2026-04-29T15:05:33.878Z","repository":{"id":98837425,"uuid":"280463578","full_name":"i2mint/py2json","owner":"i2mint","description":"Tools for json serialization of python objects","archived":false,"fork":false,"pushed_at":"2023-08-25T16:47:18.000Z","size":3132,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-05T05:26:17.019Z","etag":null,"topics":["json","python","serialization"],"latest_commit_sha":null,"homepage":"https://i2mint.github.io/py2json/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/i2mint.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-17T15:43:20.000Z","updated_at":"2023-02-24T20:22:09.000Z","dependencies_parsed_at":"2024-12-15T15:51:56.138Z","dependency_job_id":"a944cab8-78ef-4bf7-aa18-3cbbf5bdc0bc","html_url":"https://github.com/i2mint/py2json","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/i2mint/py2json","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2mint%2Fpy2json","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2mint%2Fpy2json/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2mint%2Fpy2json/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2mint%2Fpy2json/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/i2mint","download_url":"https://codeload.github.com/i2mint/py2json/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2mint%2Fpy2json/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32430818,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T13:34:34.882Z","status":"ssl_error","status_checked_at":"2026-04-29T13:34:29.830Z","response_time":110,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","python","serialization"],"created_at":"2024-12-15T15:51:40.247Z","updated_at":"2026-04-29T15:05:33.873Z","avatar_url":"https://github.com/i2mint.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# py2json\n\nA small toolkit to help serialize Python objects and callable references into JSON-friendly representations and reconstruct them. It provides:\n\n- `Ctor` — deconstruct/construct objects via a CONSTRUCTOR/ARGS/KWARGS dict representation.\n- `fakit` — a lightweight mini-language to express function calls (f, a, k) and execute them.\n- dotpath helpers — `obj_to_dotpath` and `dotpath_to_obj` for resolving dotted references.\n- helpers to extract function metadata (`obj2dict.func_info_dict`) and a JSON encoder that\n    understands numpy and bytes.\n\n# Quick examples\n\n`py2json` provides a small `JsonCodec` and `make_json_codec` factory that wire\n`Ctor` and `fakit` into a compact encode/decode interface. Instead of forcing\nyou to pick from fixed protocol names, the factory accepts a `path_parser`\nargument which is either a callable `Callable[[str], str]` or a string used as\nthe separator between module and object parts (default is '.').\n\nThis lets you support styles such as:\n\n- dotted: `package.module.attr` (default, `path_parser='.'`)\n- colon: `package.module:Class.attr` (`path_parser=':'`)\n\nThe codec normalizes path strings via the `path_parser` and evaluates `$fak`\nexpressions via `refakit` (with an injectable `func_loader` for whitelisting).\n\nExample (colon separator):\n\n```py\nfrom py2json import make_json_codec\n\ncodec = make_json_codec(path_parser=':')\nencoded = codec.encode('collections.namedtuple:MyTuple')\ndecoded = codec.decode(encoded)\n```\nTools for json serialization of python objects\n\n## A peep a bit deeper\n\nThe `JsonCodec` instance that `make_json_codec` returns uses `Ctor` and `fakit`. \nLet's have a quick peep at those.\n\nCreate a `namedtuple` using `Ctor` and instantiate it:\n\n```py\nfrom py2json.ctor import Ctor\nfrom collections import namedtuple\n\nctor_jdict = Ctor.to_ctor_dict(namedtuple, args=('A', 'x y z'))\nA = Ctor.construct(ctor_jdict)\ninst = A('one', 'two', 'three')\n```\n\nUse `fakit` to express and run a call given a dotted path:\n\n```py\nfrom py2json.fakit import fakit\nfakit({'f': 'os.path.join', 'a': ['I', 'am', 'a', 'filepath']})\n```\n\nResolve dotted references and round-trip:\n\n```py\nfrom py2json.fakit import obj_to_dotpath, dotpath_to_obj\nfrom inspect import Signature\ndot = obj_to_dotpath(Signature.replace)\nassert dotpath_to_obj(dot) is Signature.replace\n```\n\nNotes\n-----\n- `Ctor` will serialize callables to a JSON-friendly jdict with keys `{module, name, attr}` and\n    can `construct` them back into callables or instantiated objects.\n- `fakit` accepts either a callable, a dotted string, or a small structure `(f, a, k)` and\n    uses a configurable `func_loader` to resolve `f`. For security, supply a whitelist `func_loader`.\n\nSee `misc/py2json_wip.ipynb` for runnable demos.\n\n\n# Why py2json?\n\nHere we tackle the problem of serializing a python object into a json. \n\nJson is a convenient choice for web request responses or working with mongoDB for instance. \n\nIt is usually understood that we serialize an object to be able to deserialize it to recover the original object: Implicit in this is some definition of equality, which is not as trivial as it may seem. Usually **some** aspects of the deserialized object will be different, so we need to be clear on what should be the same.\n\nFor example, we probably don't care if the address of the deserialized object is different. But we probably care that it's key attributes are the same.\n\nWhat should guide us in deciding what aspects of an object should be recovered? \n\nBehavior. \n\nThe only value of an object is behavior that will ensue. This may be the behavior of all or some of the methods of a serialized instance, or the behavior of some other functions that will depend on the deserialized object. \n\nOur approach to converting a python object to a json will touch on some i2i cornerstones that are more general: Conversion and contextualization. \n\n\n## Behavior equivalence: What do we need an object to have?\n\nSay we are given the code below.\n\n```python\ndef func(obj):\n    return obj.a + obj.b\n\nclass A:\n    e = 2\n    def __init__(self, a=0, b=0, c=1, d=10):\n        self.a = a\n        self.b = b\n        self.c = c\n        self.d = d\n        \n    def target_func(self, x=3):\n        t = func(self)\n        tt = self.other_method(t)\n        return x * tt / self.e\n    \n    def other_method(self, x=1):\n        return self.c * x\n```\n\nWhich we use to make the following object\n```python\nobj = A(a=2, b=3)\n```\n\n\nSay we want to json-serialize this so that a deserialized object `dobj` is such that for all valid `obj`, resulting `dobj`, and valid `x` input:\n\n```\nobj.target_func(x) == A.target_func(obj, x) == A.target_func(dobj, x)\n```\nThe first equality is just a reminder of a python equivalence. \nThe second equality is really what we're after. \n\nWhen this is true, we'll say that `obj` and `dobj` are equivalent on `A.target_func` -- or just \"equivalent\" when the function(s) it should be equivalent is clear. \n\nTo satisfy this equality we need `dobj` to:\n- Contain all the attributes it needs to be able to compute the `A.target_func` function -- which means all the expressions contained in that function or, recursively, any functions it calls. \n- Such that the values of a same attribute of `obj` and `dobj` are equivalent (over the functions in the call try of the target function that involve these attributes.\n\nLet's have a manual look at it. \nFirst, you need to compute `func(self)`, which will require the attributes `a` and `b`. \nSecondly, you'll meed to computer `other_method`, which uses attribute `c`. \nFinally, the last expression, `x * tt / self.e` uses the attribute `e`. \n\nSo what we need to make sure we serialize the attributes: `{'a', 'b', 'c', 'e'}`. \n\nThat wasn't too hard. But it could get convoluted. Either way, we really should use computers for such boring tasks!\n\nThat's something `py2json` would like to help you with.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi2mint%2Fpy2json","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fi2mint%2Fpy2json","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi2mint%2Fpy2json/lists"}