{"id":21939118,"url":"https://github.com/futarimiti/json-fmt","last_synced_at":"2026-04-21T03:31:34.529Z","repository":{"id":38135752,"uuid":"505161637","full_name":"Futarimiti/json-fmt","owner":"Futarimiti","description":"Haskell-like comma-leading style JSON formatter","archived":false,"fork":false,"pushed_at":"2025-05-23T15:50:20.000Z","size":104,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"v3","last_synced_at":"2025-11-23T07:14:23.868Z","etag":null,"topics":["formatter","haskell","json"],"latest_commit_sha":null,"homepage":"","language":"Haskell","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/Futarimiti.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-06-19T16:25:40.000Z","updated_at":"2025-02-21T12:21:51.000Z","dependencies_parsed_at":"2024-04-04T02:26:30.904Z","dependency_job_id":"7bf380be-778c-4e4f-b2d6-25521d1217e8","html_url":"https://github.com/Futarimiti/json-fmt","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Futarimiti/json-fmt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Futarimiti%2Fjson-fmt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Futarimiti%2Fjson-fmt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Futarimiti%2Fjson-fmt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Futarimiti%2Fjson-fmt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Futarimiti","download_url":"https://codeload.github.com/Futarimiti/json-fmt/tar.gz/refs/heads/v3","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Futarimiti%2Fjson-fmt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32075222,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T02:38:07.213Z","status":"ssl_error","status_checked_at":"2026-04-21T02:38:06.559Z","response_time":128,"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":["formatter","haskell","json"],"created_at":"2024-11-29T02:16:52.222Z","updated_at":"2026-04-21T03:31:34.510Z","avatar_url":"https://github.com/Futarimiti.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# json-fmt\n\n```json\n{ \"array\": [ 1, 2, 2, 3 ]\n, \"mixedarr\": [ \"str\"\n              , true\n              , [ \"innerlist\" ]\n              ]\n, \"objarr\": [ { \"ab\": \"cd\"\n              , \"num\": 0\n              }\n            ]\n, \"number\": 123\n, \"float\": 3.1415926\n, \"string\": \"abcd\"\n, \"subobj\": { \"k1\": \"v1\"\n            , \"k2\": \"v2\"\n            , \"num\": 0.3\n            }\n}\n```\n\n### v3\n\nThere is a limitation in v2 where the order of fields within an object cannot be preserved.\nv3 addresses this by switching from `Aeson` to `json` library for parsing,\nnevertheless compromising in performance due to use of less efficient data types.\nIf you care about performance and don't mind me messing with your object entries, use v2 branch.\n\n### Install\n\n[Cabal](https://www.haskell.org/cabal/) is required. Stack should also do\n\n```sh\ngit clone 'https://github.com/Futarimiti/json-fmt'\ncd json-fmt\ncabal install\n```\n\nThere's a messy JSON [sample](resources/sample.json) for you to try out:\n\n```sh\njson-fmt resources/sample.json\n```\n\n### Usage\n\n| Command           | Description                     |\n|-------------------|---------------------------------|\n| `json-fmt`        | Format JSON input from stdin    |\n| `json-fmt \u003cFILE\u003e` | Format JSON input from `\u003cFILE\u003e` |\n\nValid JSON input is expected.\nFormatted result will be printed to stdout upon successful parse and formatting,\notherwise error message will be printed to stderr.\nUnless `-v` specified, no other output (errors, logs) will be printed.\n\n#### Flags\n\n| Flag | Description |\n|------|-------------|\n| `-v` | verbose     |\n\n### Configuration\n\nIn order, `json-fmt` will look for configurations from:\n\n*   `$JSONFMT_CONFIG`\n*   `$XDG_CONFIG_HOME/json-fmt/config.json`\n\nThe config file must be a JSON object containing key-value pairs defining each option;\ndefaults will be used for any absent options.\nSee [`resources/default-config.json`](resources/default-config.json) for reference.\nUpon failure to find or parse configurations, default configuration will be used.\nWhenever in doubt, use `-v` to find out which paths have been searched.\n\nOptions:\n\n#### `spaceNBeforeColon, spaceNAfterColon :: Int`\n\nnumber of spaces before and after a key-value separating colon.\n\n`spaceNBeforeColon = 1, spaceNAfterColon = 1`\n\n```json\n{ \"key\" : \"value\" }\n```\n\n`spaceNBeforeColon = 0, spaceNAfterColon = 1`\n\n```json\n{ \"key\": \"value\" }\n```\n\n#### `spaceNBeforeArrComma, spaceNAfterArrComma :: Int`\n\nnumber of spaces before and after a comma in a one-line array.\ndoes not affect those in multiline (see below)\n\n`spaceNBeforeArrComma = 0, spaceNAfterArrComma = 1`\n\n```json\n[1, 2, 3]\n```\n\n`spaceNBeforeArrComma = 1, spaceNAfterArrComma = 1`\n\n```json\n[1 , 2 , 3]\n```\n\n#### `arrPaddingSpaceN :: Int`\n\nnumber of spaces used as paddings for a non-empty array;\nalso affects number of spaces after every entry-separating comma, if multilined.\n\n`arrPaddingSpaceN = 1`\n\n```json\n[ 1, 2, 3 ]\n\n[ \"string1\"\n, \"string2\"\n, true\n]\n```\n\n`arrPaddingSpaceN = 2`\n\n```json\n[  1, 2, 3  ]\n[  \"string1\"\n,  \"string2\"\n,  true\n]\n```\n\n#### `spaceNInEmptyArr :: Int`\n\nnumber of spaces within an empty array.\n\n`spaceNInEmptyArr = 0`\n\n```json\n[]\n```\n\n`spaceNInEmptyArr = 2`\n\n```json\n[  ]\n```\n\n#### `spaceNInEmptyObj :: Int`\n\nnumber of spaces within an empty obj.\n\n`spaceNInEmptyObj = 0`\n\n```json\n{}\n```\n\n`spaceNInEmptyObj = 2`\n\n```json\n{  }\n```\n\n#### `objPaddingSpaceN :: Int`\n\nnumber of spaces used as paddings for a non-empty object;\nalso affects number of spaces after every entry-separating comma.\n\n`objPaddingSpaceN = 1`\n\n```json\n{ \"key\" : \"val\"\n, \"key2\" : {}\n}\n{ \"key\" : \"val\" }\n```\n\n`objPaddingSpaceN = 0`\n\n```json\n{\"key\" : \"val\"\n,\"key2\" : {}\n}\n{\"key\" : \"val\"}\n```\n\n`objPaddingSpaceN = 6`\n\n```json\n{      \"key\" : \"val\"\n,      \"key2\" : {}\n}\n{      \"key\" : \"val\"      }\n```\n\n#### `endWithNewline :: Bool`\n\nleaves an empty line at the end of document when true.\n\n#### `oneEntryOneLine :: [ValueType]`\n\nenclosing every object containing only one entry of ValueType type on the same line as the opening.\n\nDefinition of `ValueType`:\n\n```hs\ndata ValueType = Empty | Null | Bool | Number | EmptyString | NonEmptyString | FilledArray | EmptyArray | FilledObject | EmptyObject\n```\n\nInside the configuration file, use an array of strings to represent a list of value types, e.g.:\n\n```json\n{ \"oneEntryOneLine\" : [ \"Empty\", \"Null\", \"Bool\", \"Number\", \"EmptyString\" ]\n}\n```\n\n`oneEntryOneLine = [Empty, Null, Bool, Number, EmptyString, NonEmptyString, EmptyArray, EmptyObject]`\n\n```json\n{}\n{ \"nil\" : null }\n{ \"bool\" : true }\n{ \"num\" : 123 }\n{ \"str\" : \"abc\" }\n{ \"emptyarr\" : [] }\n{ \"filledarr\" : [1]\n}\n{ \"emptyobj\" : {} }\n{ \"filledobj\" : { \"a\" : \"b\" }\n}\n```\n\n`oneEntryOneLine = []`\n\n```json\n{\n}\n{ \"nil\" : null\n}\n{ \"bool\" : true\n}\n{ \"num\" : 123\n}\n{ \"str\" : \"abc\"\n}\n{ \"emptyarr\" : []\n}\n{ \"filledarr\" : [1]\n}\n{ \"emptyobj\" : {}\n}\n{ \"filledobj\" : { \"a\" : \"b\"\n\t\t\t\t}\n}\n```\n\n#### `oneElemOneLine :: [ValueType]`\n\nenclosing every array containing only one element of ValueType type on the same line as the opening.\n\n`oneElemOneLine = [Empty, Null, Bool, Number, EmptyString, NonEmptyString, EmptyObject]`\n\n```json\n[ 1 ]\n[ \"some very long string\" ]\n[ { \"obj\" : {} }\n]\n```\n\n#### `elemsOnSepLine :: [ValueType]`\n\nif an array contains one or more elements with types in \\[ValueType], put each element on separate lines.\n\n`elemsOnSepLine = [FilledObject, FilledArray]`\n\n```json\n[ 1, 2 ]\n[ true\n, 1.0\n, { \"a\" : \"b\" }\n]\n[ [ \"elem\" ]\n]\n```\n\n### Vim integration\n\n```vim\n\" ~/.vim/after/ftplugin/json.vim\nsetlocal formatprg=json-fmt\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffutarimiti%2Fjson-fmt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffutarimiti%2Fjson-fmt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffutarimiti%2Fjson-fmt/lists"}