{"id":39074764,"url":"https://github.com/dnesting/lua-jsond","last_synced_at":"2026-01-17T18:25:19.768Z","repository":{"id":291304073,"uuid":"977201453","full_name":"dnesting/lua-jsond","owner":"dnesting","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-25T13:12:39.000Z","size":39,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-25T13:47:49.136Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dnesting.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null}},"created_at":"2025-05-03T16:49:05.000Z","updated_at":"2025-05-04T20:16:12.000Z","dependencies_parsed_at":"2025-05-03T19:19:24.860Z","dependency_job_id":"1df1db4f-567b-4a2e-a879-001c1c7a4be7","html_url":"https://github.com/dnesting/lua-jsond","commit_stats":null,"previous_names":["dnesting/lua-jsond"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dnesting/lua-jsond","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnesting%2Flua-jsond","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnesting%2Flua-jsond/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnesting%2Flua-jsond/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnesting%2Flua-jsond/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dnesting","download_url":"https://codeload.github.com/dnesting/lua-jsond/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dnesting%2Flua-jsond/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28515454,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-17T17:57:59.192Z","status":"ssl_error","status_checked_at":"2026-01-17T17:57:52.527Z","response_time":85,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":[],"created_at":"2026-01-17T18:25:18.610Z","updated_at":"2026-01-17T18:25:19.744Z","avatar_url":"https://github.com/dnesting.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jsond\n\nThis is a Lua library that implements JSON decoding while preserving Wireshark TvbRange references.\nThis allows you to use JSON fields as dissector fields, allowing the UI to maintain a reference to\nthe original packet data.\n\nStatus:\nThis is under active development and unstable.\nIt's also nearly unacceptably slow and its value is questionable.\n\n# Usage\n\n```lua\njsond = require(\"jsond\")\n\njson = '{\"num_field\": 42, \"obj_field\": {\"obj_num\": 43}, \"array_field\": [\"one\", \"two\"]}'\ntvb_range = ByteArray.new(json, true):tvb()()\n\njsond     = require(\"jsond\")\ndata      = jsond.decode(tvb_range)  -- a Value\n\ntree:add(field.num_field, data.num_field())  -- unpacks into (TvbRange, number)\ntree:add(field.obj_num, data.obj_field.obj_num())\n\nfor _, val in ipairs(data.array_field) do\n  local first_letter = val:sub(1, 1)  -- \"o\", \"t\" Values\n  tree:add(field.first_letters, first_letter())\nend\n```\n\n# API Reference\n\nGenerally speaking, JSON types are decoded to standard Lua types,\nand wrapped in a class that gives you access to the associated\n[`TvbRange`](https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Tvb.html#lua_class_TvbRange)\nand value.\n\n## Functions\n\n### `jsond.decode(tvbr)`\n\nDecodes the JSON data contained in `tvbr`.\nReturns a `Value` or raises an error.\n\n```lua\nbuf  = ByteArray.new(\"42\", true):tvb()()\ndata = jsond.decode(buf)  -- Number\nprint(data:range() == buf(0, 2))\nprint(type(data:val()), data:val())\n-- true\n-- number 42\n```\n\n```lua\nbuf  = ByteArray.new(\"[42]\", true):tvb()()\ndata = jsond.decode(buf)  -- Array\nelem = data[1]            -- Number\nprint(elem:range() == buf(1, 2))\nprint(type(elem:val()), elem:val())\n-- true\n-- number 42\n```\n\n### `jsond.range(data)`\n\nReturns the [`TvbRange`](https://www.wireshark.org/docs/wsdg_html_chunked/lua_module_Tvb.html#lua_class_TvbRange) that was the source for the `Value` held by `data`.\nThis will work for all classes in the tree returned by `jsond.decode`.\nSome classes also implement a `value:range()` method as a convenience.\n\n```lua\nbuf = ByteArray.new(\"42\", true):tvb()()\ndata = jsond.decode(buf)       -- Number\nprint(jsond.range(data) == buf(0, 2))\n-- true\n```\n\n### `jsond.value(data)`\n\nReturns the Lua value represented by `data`.\nThis will be `nil` only if the `Value` represents a JSON `null`.\nMost classes also implement a `value:val()` method as a convenience.\n\nNote that the aggregated types `Array` and `Object` are represented by a Lua table. An `Array`'s elements will be `Value` instances, as are an `Object's` keys and values.\n\n```lua\nbuf = ByteArray.new(\"42\", true):tvb()()\ndata = jsond.decode(buf)  -- Number\nprint(jsond.value(data) == 42)\n-- true\n```\n\n---\n\n### `jsond.bool(data)`\n\nReturns the Lua truthiness of the Lua value of `data`. Equivalent to `not not jsond.value(data)`.\nMost classes also implement a `value:bool()` method as a convenience.\n\n### `jsond.is_zero(data)`\n\nReturns true if `data` is a number == 0, a false boolean, or an empty string, array, or object.\nMost classes also implement a `value:nonzero()` method as a convenience, equivalent to `not jsond.is_zero(data)`.\n\n```lua\nbuf = ByteArray.new('\"\"', true):tvb()()\ndata = jsond.decode(buf)  -- String\nprint(jsond.is_zero(data))\n-- true\n```\n\n### `jsond.sorted(data [, comp])`\n\nReturns an iterator over a sorted copy of `data`, which must be an `Array` or `Object`.\n\nFor an `Array`, this is equivalent to sorting its elements according to how the underlying Lua values compare to each other.  If `comp` is provided, it will be provided these underlying values.\n\nFor an `Object`, the iterator yields keys and values, sorted by key.  If `comp` is provided, it will be provided the Lua values for each key.  The values yielded by the iterator will be `Value`s.\n\n```lua\nbuf = ByteArray.new('{\"b\": 2, \"a\": 1}', true):tvb()()\ndata = jsond.decode(buf)  -- Object\nfor k, v in jsond.sorted(data) do\n  print(k, v)\nend\n-- a 1\n-- b 2\n```\n\n```lua\nbuf = ByteArray.new('[\"b\", \"a\"]', true):tvb()()\ndata = jsond.decode(buf)  -- Array\nfor i, v in jsond.sorted(data) do\n  print(i, v)\nend\n-- 1 a\n-- 2 b\n```\n\n### `jsond.type(data)`\n\nReturns the JSON type held by `data`.\nThis will be one of \"string\", \"number\", \"boolean\", \"array\", \"object\", \"null\",\nor `nil` if data isn't a `Value`.\n\n```lua\nbuf = ByteArray.new(\"42\", true):tvb()()\ndata = jsond.decode(buf)\njsond.type(data)  -- \"number\"\n```\n\n## Classes\n\n```\nValue\n├── BasicValue\n│   ├── Array\n│   ├── Boolean\n│   ├── Nil\n│   ├── Number\n│   └── String\n└── Object\n```\n\n### `Value`\n\nThe `Value` class is the superclass of the other classes below.\nIt implements a few methods that are consistent between all classes.\n\n```\nValue\n├── __call()\n└── __string()\n```\n\n#### `__call()`\n\nEvery `Value` is callable, returning `(TvbRange, value)`.\nThis is designed to facilitate use in a WireShark tree.\nThe following two lines are equivalent:\n\n```lua\ntree:add(field.my_field, data())\ntree:add(field.my_field, jsond.range(data), jsond.value(data))\n```\n\n#### `__string()`\n\nEvery `Value` supports `tostring(data)`, which is equivalent to\n`tostring(jsond.value(data))`.\n\n### `BasicValue` (`Value`)\n\n```\nValue\n├── __call()\n├── __string()\n└── BasicValue\n    ├── eq, ne, lt, le, gt, ge\n    ├── bool()     -- boolean\n    ├── nonzero()  -- boolean\n    ├── range()    -- TvbRange\n    ├── raw()      -- string\n    └── val()      -- underlying Lua value\n```\n\nA `BasicValue` is the superclass for `Array`, `Boolean`, `Nil`, `Number`, and `String`, implementing shared convenience methods absent from `Object`.\n\n### Comparators\n\nA `BasicValue` has methods allowing for comparisons against other `BasicValues` as well as standard Lua types.  For example:\n\n```lua\nbuf = ByteArray.new(\"42\", true):tvb()()\nval = jsond.decode(buf)\nprint(val == 42)  -- val is a Value, not a number\nprint(val:eq(42))\n-- false\n-- true\n```\n\nThe following methods are implemented:\n\n- `eq`, `ne`\n- `lt`, `le`\n- `gt`, `ge`\n\n### `basic:bool()`\n\nReturns the Lua truthiness of this value.\nEquivalent to `jsond.bool(basic)`.\n\n### `basic:nonzero()`\n\nReturns true if the value is non-zero, non-false, non-empty, and non-nil.\nEquivalent to `not jsond.is_zero(basic)`.\n\n#### `basic:range()`\n\nReturns the `TvbRange` corresponding to this value.  Equivalent to `jsond.range(basic)`.\n\n#### `basic:raw()`\n\nReturns the raw JSON string for this value.  Equivalent to `jsond.range(basic):raw()`.\n\n#### `basic:val()`\n\nReturns the Lua value corresponding to this value. Equivalent to `jsond.value(basic)`.\n\n### `Boolean` (`BasicValue`)\n\n`Boolean` implements no methods beyond those in `BasicValue`.\n\n### `Nil` (`BasicValue`)\n\n`Nil` implements no methods beyond those in `BasicValue` and always holds only a `nil` value (a JSON `null`).\n\n### `Number` (`BasicValue`)\n\n```\nValue\n├── __call()\n├── __string()\n└── BasicValue\n    ├── eq, ne, lt, le, gt, ge\n    ├── bool()     -- boolean\n    ├── nonzero()  -- boolean\n    ├── range()    -- TvbRange\n    ├── raw()      -- string\n    ├── val()      -- number\n    └── Number\n        └── nstime()  -- NSTime\n```\n\n#### `n:nstime()`\n\nInterprets the number as the number of seconds since the Unix `time_t` epoch and returns an `NSTime`.  Approximately equivalent to `NSTime.new(jsond.value(n))`,\nbut can handle fractional seconds as well.\n\n### `String` (`BasicValue`)\n\n```\nValue\n├── __call()\n├── __string()\n└── BasicValue\n    ├── eq, ne, lt, le, gt, ge\n    ├── bool()     -- boolean\n    ├── nonzero()  -- boolean\n    ├── range()    -- TvbRange\n    ├── raw()      -- string\n    ├── val()      -- string\n    └── String\n        ├── __len()\n        ├── byte([i [, j]])        -- Number\n        ├── ether()                -- Address\n        ├── ipv4()                 -- Address\n        ├── ipv6()                 -- Address\n        ├── lower()                -- String\n        ├── number([base])         -- Number\n        ├── sub([first [, last]))  -- String\n        └── upper()                -- String\n```\n\nA `String` holds a string value.\n\n#### `__len()`\n\n`String` supports `#string`.\n\n#### `s:byte([i [, j]])`\n\nReturns one or more `Number` instances representing the Lua code point(s) for the character(s) at index `i` (defaults to 1) through `j`, similar to the standard `string.byte` function.\n\n```lua\nbuf = ByteArray.new('\"abc\"'):tvb()()\ns = jsond.decode(buf)\nb = s:byte(2)           -- Number\nprint(b:range() == buf(2, 1))\nprint(b:val())\n-- true\n-- 98\n```\n\n#### `s:ether()`\n\nEquivalent to `Address.ether(jsond.value(s))` or `jsond.range(s):ether()`.\n\n#### `s:ipv4()`\n\nEquivalent to `Address.ipv4(jsond.value(s))` or `jsond.range(s):ipv4()`.\n\n#### `s:ipv6()`\n\nEquivalent to `Address.ipv6(jsond.value(s))` or `jsond.range(s):ipv6()`.\n\n#### `s:lower()`\n\nReturns a `String` containing a lower-cased copy of `s`.\n\n#### `s:number([base])`\n\nIf string contains numeric digits, returns a `Number`, using the optional base.\n\n#### `s:sub([first [, last]])`\n\nReturns a `String` containing the substring starting from `first` (index 1) to `last`,\ninclusive, similar to Lua's standard string `:sub()` method.\n\n```lua\nbuf = ByteArray.new('\"foobar\"'):tvb()()\ns = jsond.decode(buf)\nb = s:sub(4, 6)         -- String\nprint(b:range() == buf(4, 3))\nprint(type(b:val()), b:val())\n-- true\n-- string bar\n```\n\n#### `s:upper()`\n\nReturns a `String` containing an upper-cased copy of the string.\n\n### `Array` (`BasicValue`)\n\n```\nValue\n├── __call()\n├── __string()\n└── BasicValue\n    ├── eq, ne, lt, le, gt, ge\n    ├── bool()     -- boolean\n    ├── nonzero()  -- boolean\n    ├── range()    -- TvbRange\n    ├── raw()      -- string\n    ├── val()      -- table\n    └── Array\n        ├── __len()\n        ├── __pairs()       -- Value\n        ├── __index()       -- Value\n        ├── sorted([comp])  -- Array\n        └── sort()\n```\n\nAn `Array` holds a `table` of `Value` instances,\nindexed by numeric position.\n\n#### `__len()`\n\nAn `Array` supports `#array`.\n\n#### `__pairs()` and `__ipairs()`\n\nAn `Array` supports iteration using `pairs` and `ipairs`.\n\n#### `__index()` and `__newindex()`\n\nAn `Array` supports `array[0]`-style indexing.\n\n#### `a:sorted([comp])`\n\nReturns an iterator over the sorted values of `a`.  The `comp` comparator will be provided the underlying Lua values for each element.\n\n#### `a:sort([comp])`\n\nPerforms an in-place sort of the array's `Value`s.\nThe `comp` comparator will be provided the underlying Lua values for each element.\n\n### `Object` (`Value`)\n\n```\nValue\n├── __call()\n├── __string()\n└── Object\n    ├── __pairs()  -- String, Value\n    └── __index()  -- Value\n```\n\nAn `Object` contains a mapping from `String` keys to `Value`s.  It contains no methods in order to allow indexing of the underlying object's properties without risk of conflict.\n\nIndexing supports indexing by `String`, or a Lua string.  These references are equivalent:\n\n```lua\nbuf = ByteArray.new('{\"field\": \"value\"}', true):tvb()()\nobj = jsond.decode(buf)      -- Object\nfor k, v in pairs(obj) do\n  print(obj[k] == obj[\"field\"])\n  print(obj[k] == obj.field)\nend\n-- true\n-- true\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnesting%2Flua-jsond","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdnesting%2Flua-jsond","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdnesting%2Flua-jsond/lists"}