{"id":13468627,"url":"https://github.com/kellyjonbrazil/jello","last_synced_at":"2025-04-13T15:03:41.609Z","repository":{"id":37900205,"uuid":"249267882","full_name":"kellyjonbrazil/jello","owner":"kellyjonbrazil","description":"CLI tool to filter JSON and JSON Lines data with Python syntax. (Similar to jq)","archived":false,"fork":false,"pushed_at":"2025-03-05T17:08:42.000Z","size":631,"stargazers_count":503,"open_issues_count":4,"forks_count":23,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-04-13T15:02:48.969Z","etag":null,"topics":["bash","bash-scripting","cli","command-line","command-line-interface","command-line-tool","filter","jq","json","json-lines","process","python","query","scripting","shell-scripting"],"latest_commit_sha":null,"homepage":"","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/kellyjonbrazil.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","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-03-22T20:36:06.000Z","updated_at":"2025-03-17T14:27:37.000Z","dependencies_parsed_at":"2024-12-28T18:00:30.720Z","dependency_job_id":null,"html_url":"https://github.com/kellyjonbrazil/jello","commit_stats":{"total_commits":476,"total_committers":2,"mean_commits":238.0,"dds":"0.0021008403361344463","last_synced_commit":"72a6666a8f2eee8244613d02261c54085deed9c5"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kellyjonbrazil%2Fjello","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kellyjonbrazil%2Fjello/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kellyjonbrazil%2Fjello/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kellyjonbrazil%2Fjello/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kellyjonbrazil","download_url":"https://codeload.github.com/kellyjonbrazil/jello/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248732482,"owners_count":21152852,"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":["bash","bash-scripting","cli","command-line","command-line-interface","command-line-tool","filter","jq","json","json-lines","process","python","query","scripting","shell-scripting"],"created_at":"2024-07-31T15:01:15.237Z","updated_at":"2025-04-13T15:03:41.420Z","avatar_url":"https://github.com/kellyjonbrazil.png","language":"Python","funding_links":[],"categories":["Python","cli","\u003ca name=\"data-management-json\"\u003e\u003c/a\u003eData management - JSON/YAML/etc."],"sub_categories":[],"readme":"[![Tests](https://github.com/kellyjonbrazil/jello/workflows/Tests/badge.svg?branch=master)](https://github.com/kellyjonbrazil/jello/actions)\n[![Pypi](https://img.shields.io/pypi/v/jello.svg)](https://pypi.org/project/jello/)\n\n\u003eBuilt on `jello`:\n\u003e- [Jello Explorer](https://github.com/kellyjonbrazil/jellex) (aka `jellex`) interactive TUI\n\u003e- `jello` [web demo](https://jello-web.onrender.com)\n\n# jello\nFilter JSON and JSON Lines data with Python syntax\n\n`jello` is similar to `jq` in that it processes JSON and JSON Lines data except `jello` uses standard python dict and list syntax.\n\nJSON or JSON Lines can be piped into `jello` via STDIN or can be loaded from a JSON file or JSON Lines files (JSON Lines are automatically slurped into a list of dictionaries). Once loaded, the data is available as a python list or dictionary object named '`_`'. Processed data can be output as JSON, JSON Lines, bash array lines, or a grep-able schema.\n\nFor more information on the motivations for this project, see my [blog post](https://blog.kellybrazil.com/2020/03/25/jello-the-jq-alternative-for-pythonistas/).\n\n## Install\nYou can install `jello` via `pip`, via OS Package Repository, MSI installer for Windows, or by downloading the correct binary for your architecture and running it anywhere on your filesystem.\n\n### Pip (macOS, linux, unix, Windows)\nFor the most up-to-date version and the most cross-platform option, use `pip` or `pip3` to download and install `jello` directly from [PyPi](https://pypi.org/project/jello/):\n\n[![Pypi](https://img.shields.io/pypi/v/jello.svg)](https://pypi.org/project/jello/)\n\n```bash\npip3 install jello\n```\n\n### Packages and Binaries\n\n| OS                    | Command                  |\n|-----------------------|--------------------------|\n| Debian/Ubuntu linux   | `apt-get install jello`  |\n| Fedora linux          | `dnf install jello`      |\n| Arch linux            | `pacman -S jello`        |\n| macOS                 | `brew install jello`     |\n\n\u003e For more OS packages, see https://repology.org/project/jello/versions.\n\nSee [Releases](https://github.com/kellyjonbrazil/jello/releases) on Github for MSI packages and binaries.\n\n### Usage\n```\ncat data.json | jello [OPTIONS] [QUERY | -q \u003cquery_file\u003e]\n\njello [OPTIONS] [QUERY | -q \u003cquery_file\u003e] [-f \u003cinput_files\u003e]\n```\n`QUERY` is optional and can be most any valid python code. Alternatively, a\nquery file can be specified with `-q` to load the query from a file. Within the query, `_` is the sanitized JSON from STDIN presented as a python dict or list of dicts. If `QUERY` is omitted then the original JSON input will simply be pretty printed. You can use dot notation or traditional python bracket notation to access key names.\n\n\u003e Note: Reserved key names that cannot be accessed using dot notation can be accessed via standard python dictionary notation. (e.g. `_.foo[\"get\"]` instead of `_.foo.get`)\n\nA simple query:\n```bash\ncat data.json | jello _.foo\n```\nor\n```bash\njello _.foo -f data.json\n```\nor\n```bash\njello '_[\"foo\"]' -f data.json\n```\n\n#### Options\n- `-c` compact print JSON output instead of pretty printing\n- `-C` force color output even when using pipes (overrides `-m` and the `NO_COLOR` env variable)\n- `-e` empty data (don't process data from STDIN or file)\n- `-f` load input data from JSON file or JSON Lines files (must be the final option, if used)\n- `-i` initialize environment with a custom config file\n- `-l` lines output (suitable for bash array assignment)\n- `-m` monochrome output\n- `-n` print selected `null` values\n- `-q` load query from a file\n- `-r` raw output of selected strings (no quotes)\n- `-s` print the JSON schema in grep-able format\n- `-t` print type annotations in schema view\n- `-h` help\n- `-v` version info\n\n#### Simple Examples\n`jello` simply pretty prints the JSON if there are no options  or query passed:\n```bash\necho '{\"foo\":\"bar\",\"baz\":[1,2,3]}' | jello\n\n{\n  \"foo\": \"bar\",\n  \"baz\": [\n    1,\n    2,\n    3\n  ]\n}\n```\n\nIf you prefer compact output, use the `-c` option:\n```bash\necho '{\"foo\":\"bar\",\"baz\":[1,2,3]}' | jello -c\n\n{\"foo\":\"bar\",\"baz\":[1,2,3]}\n```\n\nUse the `-l` option to convert lists/arrays into lines:\n```bash\necho '{\"foo\":\"bar\",\"baz\":[1,2,3]}' | jello -l _.baz\n\n1\n2\n3\n```\n\nThe `-l` option also allows you to create [JSON Lines](https://jsonlines.org/):\n```bash\necho '[{\"foo\":\"bar\",\"baz\":[1,2,3]},{\"fiz\":\"boo\",\"buz\":[4,5,6]}]' | jello -l\n\n{\"foo\":\"bar\",\"baz\":[1,2,3]}\n{\"fiz\":\"boo\",\"buz\":[4,5,6]}\n```\n\nYou can print a grep-able schema by using the `-s` option:\n```bash\necho '{\"foo\":\"bar\",\"baz\":[1,2,3]}' | jello -s\n\n_ = {};\n_.foo = \"bar\";\n_.baz = [];\n_.baz[0] = 1;\n_.baz[1] = 2;\n_.baz[2] = 3;\n```\n\n#### Assigning Results to a Bash Array\n\nUse the `-l` option to print JSON array output in a manner suitable to be assigned to a bash array. The `-r` option can be used to remove quotation marks around strings. If you want `null` values to be printed as `null`, use the `-n` option, otherwise they are printed as blank lines.\n\nBash variable:\n```\nvariable=($(cat data.json | jello -rl _.foo))\n```\n\nBash array variable (Bash 4+):\n```\nmapfile -t variable \u003c \u003c(cat data.json | jello -rl _.foo)\n```\n\nBash array variable (older versions of Bash):\n```\nvariable=()\nwhile read -r value; do\n    variable+=(\"$value\")\ndone \u003c \u003c(cat data.json | jello -rl _.foo)\n```\n\n### Setting Custom Colors via Environment Variable\nCustom colors can be set via the `JELLO_COLORS` environment variable. Any colors set in the environment variable will take precedence over any colors set in the initialization file. (see [Advanced Usage](https://github.com/kellyjonbrazil/jello/blob/master/ADVANCED_USAGE.md))\n\nThe `JELLO_COLORS` environment variable takes four comma separated string values in the following format:\n```\nJELLO_COLORS=\u003ckeyname_color\u003e,\u003ckeyword_color\u003e,\u003cnumber_color\u003e,\u003cstring_color\u003e\n```\nWhere colors are: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `gray`, `brightblack`, `brightred`, `brightgreen`, `brightyellow`, `brightblue`, `brightmagenta`, `brightcyan`, `white`, or  `default`\n\nFor example, to set to the default colors:\n```\nJELLO_COLORS=blue,brightblack,magenta,green\n```\nor\n```\nJELLO_COLORS=default,default,default,default\n```\n\n### Disable Colors via Environment Variable\nYou can set the [`NO_COLOR`](http://no-color.org/) environment variable to any value to disable color output in `jello`. Note that using the `-C` option to force color output will override both the `NO_COLOR` environment variable and the `-m` option.\n\n### Advanced Usage\nHere is more [Advanced Usage](https://github.com/kellyjonbrazil/jello/blob/master/ADVANCED_USAGE.md) information.\n\n\u003e To accelerate filter development and testing, try [`jellex`](https://github.com/kellyjonbrazil/jellex). `jellex` is an interactive front-end TUI built on `jello` that allows you to see your filter results in real-time along with any errors.\n\n## Examples:\n### Printing the Grep-able Schema\n```bash\n$ jc -a | jello -s\n\n_ = {};\n_.name = \"jc\";\n_.version = \"1.17.2\";\n_.description = \"JSON CLI output utility\";\n_.author = \"Kelly Brazil\";\n_.author_email = \"kellyjonbrazil@gmail.com\";\n_.website = \"https://github.com/kellyjonbrazil/jc\";\n_.copyright = \"© 2019-2021 Kelly Brazil\";\n_.license = \"MIT License\";\n_.parser_count = 80;\n_.parsers = [];\n_.parsers[0] = {};\n_.parsers[0].name = \"acpi\";\n_.parsers[0].argument = \"--acpi\";\n_.parsers[0].version = \"1.2\";\n_.parsers[0].description = \"`acpi` command parser\";\n_.parsers[0].author = \"Kelly Brazil\";\n_.parsers[0].author_email = \"kellyjonbrazil@gmail.com\";\n_.parsers[0].compatible = [];\n_.parsers[0].compatible[0] = \"linux\";\n_.parsers[0].magic_commands = [];\n_.parsers[0].magic_commands[0] = \"acpi\";\n_.parsers[1] = {};\n_.parsers[1].name = \"airport\";\n_.parsers[1].argument = \"--airport\";\n_.parsers[1].version = \"1.3\";\n...\n```\n### Printing the Grep-able Schema with type annotations (useful for grepping types)\n```bash\njc dig example.com | jello -st\n\n_ = [];                                                             //   (array)\n_[0] = {};                                                          //  (object)\n_[0].id = 23819;                                                    //  (number)\n_[0].opcode = \"QUERY\";                                              //  (string)\n_[0].status = \"NOERROR\";                                            //  (string)\n_[0].flags = [];                                                    //   (array)\n_[0].flags[0] = \"qr\";                                               //  (string)\n_[0].flags[1] = \"rd\";                                               //  (string)\n_[0].flags[2] = \"ra\";                                               //  (string)\n_[0].query_num = 1;                                                 //  (number)\n_[0].answer_num = 1;                                                //  (number)\n_[0].authority_num = 0;                                             //  (number)\n_[0].additional_num = 1;                                            //  (number)\n_[0].opt_pseudosection = {};                                        //  (object)\n_[0].opt_pseudosection.edns = {};                                   //  (object)\n_[0].opt_pseudosection.edns.version = 0;                            //  (number)\n_[0].opt_pseudosection.edns.flags = [];                             //   (array)\n_[0].opt_pseudosection.edns.udp = 4096;                             //  (number)\n_[0].question = {};                                                 //  (object)\n_[0].question.name = \"example.com.\";                                //  (string)\n_[0].question.class = \"IN\";                                         //  (string)\n_[0].question.type = \"A\";                                           //  (string)\n_[0].answer = [];                                                   //   (array)\n_[0].answer[0] = {};                                                //  (object)\n_[0].answer[0].name = \"example.com.\";                               //  (string)\n_[0].answer[0].class = \"IN\";                                        //  (string)\n_[0].answer[0].type = \"A\";                                          //  (string)\n_[0].answer[0].ttl = 48358;                                         //  (number)\n_[0].answer[0].data = \"93.184.216.34\";                              //  (string)\n_[0].query_time = 46;                                               //  (number)\n_[0].server = \"2600:1700:bab0:d40::1#53(2600:1700:bab0:d40::1)\";    //  (string)\n_[0].when = \"Mon Nov 29 09:41:11 PST 2021\";                         //  (string)\n_[0].rcvd = 56;                                                     //  (number)\n_[0].when_epoch = 1638207671;                                       //  (number)\n_[0].when_epoch_utc = null;                                         //    (null)\n```\n### Printing the Structure of the JSON\n```bash\njc dig example.com | jello -st | grep '(object)\\|(array)'\n\n_ = [];                                                             //   (array)\n_[0] = {};                                                          //  (object)\n_[0].flags = [];                                                    //   (array)\n_[0].opt_pseudosection = {};                                        //  (object)\n_[0].opt_pseudosection.edns = {};                                   //  (object)\n_[0].opt_pseudosection.edns.flags = [];                             //   (array)\n_[0].question = {};                                                 //  (object)\n_[0].answer = [];                                                   //   (array)\n_[0].answer[0] = {};                                                //  (object)\n```\n### Lambda Functions and Math\n```bash\necho '{\"t1\":-30, \"t2\":-20, \"t3\":-10, \"t4\":0}' | jello '\\\nkeys = _.keys()\nvals = _.values()\ncel = list(map(lambda x: (float(5)/9)*(x-32), vals))\ndict(zip(keys, cel))'\n\n{\n  \"t1\": -34.44444444444444,\n  \"t2\": -28.88888888888889,\n  \"t3\": -23.333333333333336,\n  \"t4\": -17.77777777777778\n}\n\n```\n\n```bash\njc -a | jello 'len([entry for entry in _.parsers if \"darwin\" in entry.compatible])'\n\n45\n```\n\n### For Loops\nOutput as JSON array\n```bash\njc -a | jello '\\\nresult = []\nfor entry in _.parsers:\n  if \"darwin\" in entry.compatible:\n    result.append(entry.name)\nresult'\n\n[\n  \"airport\",\n  \"airport_s\",\n  \"arp\",\n  \"crontab\",\n  \"crontab_u\",\n  ...\n]\n```\nOutput as bash array\n```bash\njc -a | jello -rl '\\\nresult = []\nfor entry in _.parsers:\n  if \"darwin\" in entry.compatible:\n    result.append(entry.name)\nresult'\n\nairport\nairport_s\narp\ncrontab\ncrontab_u\n...\n```\n### List and Dictionary Comprehension\nOutput as JSON array\n```bash\njc -a | jello '[entry.name for entry in _.parsers if \"darwin\" in entry.compatible]'\n\n[\n  \"airport\",\n  \"airport_s\",\n  \"arp\",\n  \"crontab\",\n  \"crontab_u\",\n  ...\n]\n```\n\nOutput as bash array\n```bash\njc -a | jello -rl '[entry.name for entry in _.parsers if \"darwin\" in entry.compatible]'\n\nairport\nairport_s\narp\ncrontab\ncrontab_u\n...\n```\n\n### Expressions and Environment Variables\n```bash\necho '{\"login_name\": \"joeuser\"}' | jello 'os.getenv(\"LOGNAME\") == _.login_name'\n\ntrue\n```\n\n### Using 3rd Party Modules\nYou can import and use your favorite modules to manipulate the data.  For example, using `glom`:\n```bash\njc -a | jello '\\\nfrom glom import *\nglom(_, (\"parsers\", [\"name\"]))'\n\n[\n  \"airport\",\n  \"airport_s\",\n  \"arp\",\n  \"blkid\",\n  \"crontab\",\n  \"crontab_u\",\n  \"csv\",\n  ...\n]\n```\n\n### Advanced JSON Manipulation\nThe data from this example comes from https://programminghistorian.org/assets/jq_twitter.json\n\nUnder **Grouping and Counting**, Matthew describes an advanced `jq` filter against a sample Twitter dataset that includes JSON Lines data. There he describes the following query:\n\n\u003e \"We can now create a table of users. Let’s create a table with columns for the user id, user name, followers count, and a column of their tweet ids separated by a semicolon.\"\n\nhttps://programminghistorian.org/en/lessons/json-and-jq\n\nHere is a simple solution using `jello`:\n```bash\ncat jq_twitter.json | jello -l '\\\nuser_ids = set()\nfor tweet in _:\n    user_ids.add(tweet.user.id)\nresult = []\nfor user in user_ids:\n    user_profile = {}\n    tweet_ids = []\n    for tweet in _:\n        if tweet.user.id == user:\n            user_profile.update({\n                \"user_id\": user,\n                \"user_name\": tweet.user.screen_name,\n                \"user_followers\": tweet.user.followers_count})\n            tweet_ids.append(str(tweet.id))\n    user_profile[\"tweet_ids\"] = \";\".join(tweet_ids)\n    result.append(user_profile)\nresult'\n\n...\n{\"user_id\": 2696111005, \"user_name\": \"EGEVER142\", \"user_followers\": 1433, \"tweet_ids\": \"619172303654518784\"}\n{\"user_id\": 42226593, \"user_name\": \"shirleycolleen\", \"user_followers\": 2114, \"tweet_ids\": \"619172281294655488;619172179960328192\"}\n{\"user_id\": 106948003, \"user_name\": \"MrKneeGrow\", \"user_followers\": 172, \"tweet_ids\": \"501064228627705857\"}\n{\"user_id\": 18270633, \"user_name\": \"ahhthatswhy\", \"user_followers\": 559, \"tweet_ids\": \"501064204661850113\"}\n{\"user_id\": 14331818, \"user_name\": \"edsu\", \"user_followers\": 4220, \"tweet_ids\": \"615973042443956225;618602288781860864\"}\n{\"user_id\": 2569107372, \"user_name\": \"SlavinOleg\", \"user_followers\": 35, \"tweet_ids\": \"501064198973960192;501064202794971136;501064214467731457;501064215759568897;501064220121632768\"}\n{\"user_id\": 22668719, \"user_name\": \"nodehyena\", \"user_followers\": 294, \"tweet_ids\": \"501064222772445187\"}\n...\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkellyjonbrazil%2Fjello","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkellyjonbrazil%2Fjello","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkellyjonbrazil%2Fjello/lists"}