{"id":27107317,"url":"https://github.com/planetis-m/jsonpak","last_synced_at":"2025-11-02T17:01:47.226Z","repository":{"id":44369179,"uuid":"405881245","full_name":"planetis-m/jsonpak","owner":"planetis-m","description":"Packed ASTs for compact and efficient JSON representation, with JSON Pointer, JSON Patch support.","archived":false,"fork":false,"pushed_at":"2024-05-01T18:52:43.000Z","size":337,"stargazers_count":21,"open_issues_count":7,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-05-02T04:20:17.449Z","etag":null,"topics":["json","json-patch","json-pointer","nim","nim-lang"],"latest_commit_sha":null,"homepage":"https://planetis-m.github.io/jsonpak/","language":"Nim","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/planetis-m.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":"2021-09-13T07:49:55.000Z","updated_at":"2024-05-11T21:26:55.432Z","dependencies_parsed_at":"2024-05-11T21:26:55.170Z","dependency_job_id":"731d415d-a55f-49af-91da-6c7caf0827ac","html_url":"https://github.com/planetis-m/jsonpak","commit_stats":null,"previous_names":["planetis-m/jsonpak"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetis-m%2Fjsonpak","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetis-m%2Fjsonpak/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetis-m%2Fjsonpak/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/planetis-m%2Fjsonpak/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/planetis-m","download_url":"https://codeload.github.com/planetis-m/jsonpak/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247548795,"owners_count":20956800,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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","json-patch","json-pointer","nim","nim-lang"],"created_at":"2025-04-06T20:33:23.101Z","updated_at":"2025-11-02T17:01:47.117Z","avatar_url":"https://github.com/planetis-m.png","language":"Nim","readme":"# jsonpak - Yet another JSON library\n\njsonpak is JSON library that implements the JSON Patch RFC which is specified in\n[RFC 6902](https://datatracker.ietf.org/doc/html/rfc5789/) from the IETF.\n\nIt uses Packed ASTs for compact and efficient JSON representation. Based on Araq's\n[idea](https://github.com/planetis-m/jsonecs/issues/8).\n\n## Documentation\n\nAPI [documentation](https://planetis-m.github.io/jsonpak/)\n\nFor more information visit: \u003chttps://jsonpatch.com/\u003e or the linked RFC documents.\n\n### JSON Pointer\n\n```nim\n\ntype\n  JsonPtr* = distinct string\n\n```\n\nJSON Pointer [(IETF RFC 6901)](https://datatracker.ietf.org/doc/html/rfc6901/) defines a\nstring format for identifying a specific value within a JSON document. It is used by all\noperations in JSON Patch to specify the part of the document to operate on.\n\nA JSON Pointer is a string of tokens separated by `/` characters, these tokens either\nspecify keys in objects or indexes into arrays. For example, given the JSON\n\n```json\n\n{\n  \"a\": [1, 2, 3],\n  \"b\": 4,\n  \"c\": [5, 6],\n  \"d\": {\"e\": [7, 8], \"f\": 9}\n}\n\n```\n\n`/d/e` would point to the array of ints `[7, 8]` and `/d/e/0` would point to `7`.\n\nTo point to the root of the document use an empty string for the pointer. The pointer\n`/` doesn’t point to the root, it points to a key of `\"\"` on the root (which is\ntotally valid in JSON).\n\nIf you need to refer to a key with `~` or `/` in its name, you must escape the\ncharacters with `~0` and `~1` respectively. For example, to get `\"baz\"` from\n`{\"foo/bar~\": \"baz\" }` you’d use the pointer `/foo~1bar~0`.\n\nFinally, if you need to refer to the end of an array you can use `-` instead of an\nindex. For example, to refer to the end of the array above you would use\n`/a/-`. This is useful when you need to insert a value at the end of an array.\n\n### Operations\n\n#### Add\n\n```nim\n\nproc add(tree: var JsonTree; path: JsonPtr; value: JsonTree)\n\n```\n\nAdds a value to an object or inserts it into an array. In the case of an array, the value\nis inserted before the given index. The `-` character can be used instead of an index to\ninsert at the end of an array.\n\n#### Remove\n\n```nim\n\nproc remove(tree: var JsonTree; path: JsonPtr)\n\n```\n\nRemoves a value from an object or array.\n\n#### Replace\n\n```nim\n\nproc replace(tree: var JsonTree; path: JsonPtr, value: JsonTree)\n\n```\n\nReplaces a value. Equivalent to a `remove` followed by an `add`.\n\n#### Copy\n\n```nim\n\nproc copy(tree: var JsonTree; `from`, path: JsonPtr)\n\n```\n\nCopies a value from one location to another within the JSON document. Both `from` and\n`path` are JSON Pointers.\n\n#### Move\n\n```nim\n\nproc move(tree: var JsonTree; `from`, path: JsonPtr)\n\n```\n\nMoves a value from one location to the other. Both `from` and `path` are JSON Pointers.\n\n#### Test\n\n```nim\n\nproc test(tree: JsonTree; path: JsonPtr, value: JsonTree): bool\n\n```\n\nTests that the specified value is set in the document.\n\n### Misc\n\n```nim\n\n# JsonTree type (import jsonpak, jsonpak/dollar)\nproc `==`(a, b: JsonTree): bool\nproc isEmpty(tree: JsonTree): bool\nproc newEmptyTree(): JsonTree\nproc copy(tree: JsonTree): JsonTree\nproc `$`(tree: JsonTree): string\n# basic usage (import jsonpak/extra)\nproc len(tree: JsonTree; path: JsonPtr): int\nproc kind(tree: JsonTree; path: JsonPtr): JsonNodeKind\nproc contains(tree: JsonTree; path: JsonPtr): bool\nproc extract(tree: JsonTree; path: JsonPtr): JsonTree\nproc dump(tree: JsonTree; path: JsonPtr): string\n# (de)serialize (import jsonpak/[builder, mapper])\nproc fromJson[T](tree: JsonTree; path: JsonPtr; t: typedesc[T]): T\nproc toJson[T](x: T): JsonTree\nmacro `%*`(x: untyped): JsonTree\n# iterators (import jsonpak/builder)\niterator items[T](tree: JsonTree; path: JsonPtr; t: typedesc[T]): T\niterator pairs[T](tree: JsonTree; path: JsonPtr; t: typedesc[T]): (lent string, T)\n# SortedJsonTree type (import jsonpak/sorted)\nproc sorted(tree: JsonTree): SortedJsonTree\nproc `==`(a, b: SortedJsonTree): bool\nproc deduplicate(tree: var SortedJsonTree)\nproc hash(tree: SortedJsonTree): Hash\n\n```\n\n### Examples\n\n```nim\n\nimport jsonpak, jsonpak/[patch, parser, jsonptr, extra, builder, mapper, sorted, dollar]\n\nvar x = %*{\n  \"a\": [1, 2, 3],\n  \"b\": 4,\n  \"c\": [5, 6],\n  \"d\": {\"e\": [7, 8], \"f\": 9}\n}\n\n# Basic usage\nassert len(x, JsonPtr\"\") == 4\nassert contains(x, JsonPtr\"/a\")\nassert kind(x, JsonPtr\"/a\") == JArray\n\nadd x, JsonPtr\"/a/-\", %*[5, 6]\n# {\"a\":[1,2,3,[5,6]],\"b\":4,\"c\":[5,6],\"d\":{\"e\":[7,8],\"f\":9}}\n\nremove x, JsonPtr\"/d/e/1\"\n# {\"a\":[1,2,3,[5,6]],\"b\":4,\"c\":[5,6],\"d\":{\"e\":[7],\"f\":9}}\n\nreplace x, JsonPtr\"/b\", %*\"foo\"\n# {\"a\":[1,2,3,[5,6]],\"b\":\"foo\",\"c\":[5,6],\"d\":{\"e\":[7],\"f\":9}}\n\ncopy x, JsonPtr\"/b\", JsonPtr\"/d/f\"\n# {\"a\":[1,2,3,[5,6]],\"b\":\"foo\",\"c\":[5,6],\"d\":{\"e\":[7],\"f\":\"foo\"}}\n\nmove x, JsonPtr\"/c\", JsonPtr\"/b\"\n# {\"a\":[1,2,3,[5,6]],\"b\":[5,6],\"d\":{\"e\":[7],\"f\":\"foo\"}}\n\n# Comparing, copying, deserializing\nassert test(x, JsonPtr\"/d\", %*{\"e\": [7], \"f\": \"foo\"})\nassert $extract(x, JsonPtr\"/d\") == \"\"\"{\"e\":[7],\"f\":\"foo\"}\"\"\"\nassert fromJson(x, JsonPtr\"/a/3\", seq[int]) == @[5, 6]\nassert toJson(@[5, 6]) == extract(x, JsonPtr\"/b\")\n# Iterating\nfor i in items(x, JsonPtr\"/b\", int): echo i, \" \"\n# 5 6\nfor k, v in pairs(x, JsonPtr\"/d\", JsonTree): echo (k, v), \" \"\n# (\"e\", [7]) (\"f\", \"foo\")\n\n# Sorting, deduplicating, repeatable hashes\nvar y = parseJson(\"\"\"{\"b\":5,\"a\":1,\"b\":{\"d\":4,\"c\":2,\"d\":3}}\"\"\").sorted\ndeduplicate(y)\n# {\"a\": 1, \"b\": {\"c\": 2, \"d\": 3}}\necho hash(y) # -3485509795705892506\n\n```\n\n## Benchmarks\n\nThis section details the average time (in milliseconds) it takes to perform\nvarious operations on a JSON document containing 1,000 entries.\n\n| Op\\Lib   | jsonpak  | std/json |\n|----------|----------|----------|\n| Extract  | 0.2679   | 0.6892   |\n| toString | 0.8314   | 0.6853   |\n| fromJson | 0.0040   | 0.0008   |\n| toJson   | 0.0007   | 0.0005   |\n| Parse    | 0.9767   | 1.4560   |\n| Test     | 0.0041   | 0.0005   |\n| Replace  | 0.0043   | 0.0005   |\n| Remove   | 0.0131   | 0.0008   |\n| Add      | 0.0043   | 0.0005   |\n| Copy     | 0.0086   | 0.0005   |\n| Move     | 0.0179   | 0.0008   |\n| Sort     | 0.8483   | 0.1953   |\n| Hash     | 0.1045   | 0.1484   |\n\nHowever, the standard library's representation occupies approximately 13.4MiB,\nwhereas ours only takes up 2.8MiB. Therefore, this library aims to optimize\nfor space, and further improvements are planned.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplanetis-m%2Fjsonpak","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fplanetis-m%2Fjsonpak","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fplanetis-m%2Fjsonpak/lists"}