{"id":17124935,"url":"https://github.com/shellyln/go-loose-json-parser","last_synced_at":"2026-05-02T14:43:26.096Z","repository":{"id":65695893,"uuid":"597352248","full_name":"shellyln/go-loose-json-parser","owner":"shellyln","description":"Super loose JSON + TOML parsers and unmarshaller for Go. JSONC and JSON5 can also be read.","archived":false,"fork":false,"pushed_at":"2023-05-04T00:08:29.000Z","size":91,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-29T09:44:58.729Z","etag":null,"topics":["go","golang","golang-library","json","json-parser","json5","json5-parser","jsonc","jsonc-parser","loose-json","toml","toml-parser"],"latest_commit_sha":null,"homepage":"","language":"Go","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/shellyln.png","metadata":{"files":{"readme":"README.md","changelog":"Changelog.md","contributing":null,"funding":null,"license":"LICENSE.md","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":"2023-02-04T09:23:38.000Z","updated_at":"2023-05-06T11:15:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"ca23a4ac-eb61-4c5a-b79e-d0de4a018720","html_url":"https://github.com/shellyln/go-loose-json-parser","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shellyln%2Fgo-loose-json-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shellyln%2Fgo-loose-json-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shellyln%2Fgo-loose-json-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shellyln%2Fgo-loose-json-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shellyln","download_url":"https://codeload.github.com/shellyln/go-loose-json-parser/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245204399,"owners_count":20577343,"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":["go","golang","golang-library","json","json-parser","json5","json5-parser","jsonc","jsonc-parser","loose-json","toml","toml-parser"],"created_at":"2024-10-14T18:43:43.770Z","updated_at":"2026-05-02T14:43:26.062Z","avatar_url":"https://github.com/shellyln.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Loose JSON + TOML parsers for Go\nSuper loose JSON + TOML parsers and unmarshaller for Go.  \nJSONC and JSON5 can also be read.\n\n[![Test](https://github.com/shellyln/go-loose-json-parser/actions/workflows/test.yml/badge.svg)](https://github.com/shellyln/go-loose-json-parser/actions/workflows/test.yml)\n[![release](https://img.shields.io/github/v/release/shellyln/go-loose-json-parser)](https://github.com/shellyln/go-loose-json-parser/releases)\n[![Go version](https://img.shields.io/github/go-mod/go-version/shellyln/go-loose-json-parser)](https://github.com/shellyln/go-loose-json-parser)\n\n\u003cimg src=\"https://raw.githubusercontent.com/shellyln/go-loose-json-parser/master/_assets/logo-go-jsonlp.svg\" alt=\"logo\" style=\"width:250px;\" width=\"250\"\u003e\n\n---\n\n## 📦 Example app\n\n* [Loose JSON | TOML normalizer](https://shellyln.github.io/jsonlp/) (WebAssembly)\n    * Normalize loose JSON | TOML to strict JSON\n    * [Code](https://github.com/shellyln/go-loose-json-parser/blob/master/cmd/wasm/main.go)\n\n## 🚀 Getting started\n\n### JSON\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com/shellyln/go-loose-json-parser/jsonlp\"\n)\n\nfunc main() {\n    // src: Loose JSON\n    //\n    // plafLb:\n    // * Platform-dependent line break.\n    //   * `Linebreak_Lf` | `Linebreak_CrLf` | `Linebreak_Cr`\n    // * Line break codes in multi-line string are replaced by this specified line break.\n    //   (Excluding line breaks by escape sequences)\n    //\n    // interop:\n    // * If `Interop_JSON` is set,\n    //   replace NaN, Infinity, complex number\n    //   by `{nan:true}`, `{inf:+/-1}`, `{re:re,im:im}` .\n    // * If `Interop_TOML` is set,\n    //   replace complex number by `{re:re,im:im}` .\n    // * If `Interop_JSON_AsNull` is set,\n    //   replace NaN, Infinity, complex number by null.\n    // * If `Interop_TOML_AsNull` is set,\n    //   replace complex number by null.\n    //\n    // parsed:\n    //   nil | []any | map[string]any |\n    //   float64 | int64 | uint64 | complex128 |\n    //   string | bool | time.Time\n    parsed, err := jsonlp.ParseJSON(`{\n        // comment\n        config: {\n            addr: '127.0.0.1',\n        }\n    }`, jsonlp.Linebreak_Lf, jsonlp.Interop_None)\n\n    if err != nil {\n        fmt.Printf(\"Parse: error = %v\\n\", err)\n        return\n    }\n\n    fmt.Printf(\"Parsed = %v\\n\", parsed)\n}\n```\n\n### TOML\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com/shellyln/go-loose-json-parser/jsonlp\"\n)\n\nfunc main() {\n    // src: Loose TOML\n    //\n    // plafLb:\n    // * Platform-dependent line break.\n    //   * `Linebreak_Lf` | `Linebreak_CrLf` | `Linebreak_Cr`\n    // * Line break codes in multi-line string are replaced by this specified line break.\n    //   (Excluding line breaks by escape sequences)\n    //\n    // interop:\n    // * If `Interop_JSON` is set,\n    //   replace NaN, Infinity, complex number\n    //   by `{nan:true}`, `{inf:+/-1}`, `{re:re,im:im}` .\n    // * If `Interop_TOML` is set,\n    //   replace complex number by `{re:re,im:im}` .\n    // * If `Interop_JSON_AsNull` is set,\n    //   replace NaN, Infinity, complex number by null.\n    // * If `Interop_TOML_AsNull` is set,\n    //   replace complex number by null.\n    //\n    // parsed:\n    //   nil | []any | map[string]any |\n    //   float64 | int64 | uint64 | complex128 |\n    //   string | bool | time.Time\n    parsed, err := jsonlp.ParseTOML(`\n    # comment\n    [config]\n    addr = '127.0.0.1'\n    `, jsonlp.Linebreak_Lf, jsonlp.Interop_None)\n\n    if err != nil {\n        fmt.Printf(\"Parse: error = %v\\n\", err)\n        return\n    }\n\n    fmt.Printf(\"Parsed = %v\\n\", parsed)\n}\n```\n\n### Unmarshal\nMapping untyped data to a typed variable.\n```go\npackage main\n\nimport (\n    \"fmt\"\n    \"github.com/shellyln/go-loose-json-parser/jsonlp\"\n    \"github.com/shellyln/go-loose-json-parser/marshal\"\n)\n\ntype config struct {\n    Addr string `json:\"addr\"`\n}\n\ntype response struct {\n    Config config `json:\"config\"`\n}\n\nfunc main() {\n    parsed, err := jsonlp.ParseJSON(`{\n        // comment\n        config: {\n            addr: '127.0.0.1',\n        }\n    }`, jsonlp.Linebreak_Lf, jsonlp.Interop_None)\n\n    if err != nil {\n        fmt.Printf(\"Parse: error = %v\\n\", err)\n        return\n    }\n\n    var typed response\n\n    // src:  Source data. Untyped in typical use.\n    // dst:  Pointer to result data. Typed in typical use.\n    // opts: Pointer to struct of the `Unmarshal` options. If nil, use default.\n    //       Default options are {\n    //           TagName: \"json\",               // Tag name of the struct fields\n    //           NoCopyUnexportedFields: false, // If true, no shallow copying of unexported fields\n    //           NoCustomMarshaller: false,     // If true, IMarshal and IUnmarshal are not used\n    //       }\n    if err := marshal.Unmarshal(parsed, \u0026typed, nil); err != nil {\n        fmt.Printf(\"Unmarshal: error = %v\\n\", err)\n        return\n    }\n\n    fmt.Printf(\"Typed = %v\\n\", typed)\n}\n\n```\n\n\u003e **Note**  \n\u003e `Unmarshal` also works well for typed to untyped conversions and as deep cloning.\n\n## 🥅 Goal\n* ✅ Can read strict TOML.\n* ✅ Can read loose JSON, JSONC, JSON5, and TOML for configuration files.\n* ✅ Can be mapped to structs, untyped maps/slices, or primitives.\n* ✅ Can read many list and map literals in JavaScript, Python, PHP, Ruby, etc.\n\n## 🚧 ToDo\n\n### APIs\n\n* ✅ ~~Marshalling from any to typed~~\n\n### TOML\n\n* ✅ ~~Datetime format with date and time delimited by space (RFC 3339 section 5.6)~~\n  * ~~e.g. `2006-01-02 15:04:05Z`~~\n* ✅ ~~Datetime format without timezone~~\n  * ~~e.g. `2006-01-02T15:04:05`~~\n* ✅ ~~Platform-dependent newline in multiline string~~\n* Error detection when values are overwritten\n\n\n## 🪄 Examples\n\n### JSON\n\n```js\n# Hash comment\n{\n    // Line comment\n    /* Block comment */\n\n    // Object keys can be enclosed in either double-quote, single-quote, back-quote.\n    // It is also allowed not to enclose them.\n\n    \"foo\": [\n        123,          // -\u003e float64(123)\n        -123.45,      // -\u003e float64(-123.45)\n        -1.2345e+6,   // -\u003e float64(-1234500)\n        -123_456_789, // -\u003e float64(-123456789)\n        0x12345678,   // -\u003e float64(305419896)\n        0x1234_5678,  // -\u003e float64(305419896)\n        0o7654_3210,  // -\u003e float64(16434824)\n        0b0101_0101,  // -\u003e float64(85)\n    ],\n\n    'bar': null,      // -\u003e nil\n    baz: undefined,   // -\u003e nil\n    \"qux\": -Infinity, // -\u003e -Inf // Infinity, +Infinity are also available\n    \"quux\": NaN,      // -\u003e NaN\n\n    // Non-ASCII identifiers can also be used.\n    あいうえお: {\n        key: \"value1\",\n        bare_key: \"value2\",\n        bare-key: \"value3\", // Keys containing hyphens are allowed.\n        1234: \"value4\",     // Keys starting with a number are allowed.\n        -3.14: \"value5\",    // \"-3\": { \"14\": \"value5\" }\n    },\n\n    \"corge\": [\n        // Escape sequences are available\n        'Hello, World!\\r\\n',\n\n        // Unicode escape sequences (\\uXXXX and \\u{XXXXXX}) are available\n        \"\\u0048\\u0065\\u006c\\u006c\\u006f\\u002c\\u0020\\u0057\\u006f\\u0072\\u006c\\u0064\\u0021\",\n\n        // Byte escape sequence is also available\n        \"\\x48\\x65\\x6c\\x6c\\x6f\\x2c\\x20\\x57\\x6f\\x72\\x6c\\x64\\x21\",\n\n        // Multiline string literal\n        `Tempor adipiscing amet velit ipsum diam ut ea takimata lorem gubergren sed laoreet.\n        Congue possim facilisis sea justo dolore amet eos dolores est magna.`\n    ],\n\n    \"grault\": [\n        // Date, Time, DateTime literals are available\n\n        2020-12-31,              // -\u003e time.Time 2020-12-31:00:00.000Z\n        18:20:30.001,            // -\u003e time.Time 1870-01-01T18:20:30.001Z\n        2020-12-31T18:20:30.001Z // -\u003e time.Time 2020-12-31:20:30.001Z\n    ],\n\n    // \"key = value\" syntax is allowed\n    garply = true,\n\n    // \"key =\u003e value\" syntax is allowed\n    waldo =\u003e false,\n\n    // Trailing commas are allowed.\n    fred: 10,\n}\n```\n\nSee also: [Introducing JSON](https://www.json.org/json-en.html), [JSON5 Spec](https://spec.json5.org/)\n\n### TOML\n\n```toml\n# Hash comment\n// Line comment (non-standard)\n/* Block comment (non-standard) */\n\n\"quoted-key\" = \"value0\"\nkey          = \"value1\"\nbare_key     = \"value2\"\nbare-key     = \"value3\"  # Keys containing hyphens are allowed.\n1234         = \"value4\"  # Keys starting with a number are allowed.\n-3.14        = \"value5\"  # \"-3\": { \"14\": \"value5\" }\nあいうえお    = \"value6\"  # // Non-ASCII identifiers are allowed. (non-standard)\n\n[table-A]\nitem-a = 1\nitem-b = 2\nitem-c = \"standard\\n string\"\nitem-d = '\\literal string'\nitem-e = \"\"\"\\\n         Multiline \\\n         standard string\"\"\"\nitem-f = '''\nMultiline\nliteral string''' \"\\t\" '''!!'''\n\n[table-A.sub-table-P]\nitem-m = 11\nitem-n = 12\nsub-table-X.sub-table-Y = 111\n\n[[array-of-table-U]]\nfoo = 1\n[array-of-table-U.sub-table-V]\nbar = 11\n\n[[array-of-table-U]]\nfoo = 2\n[array-of-table-U.sub-table-V]\nbar = 22\n```\n\nSee also: [TOML Spec](https://toml.io/en/v1.0.0)\n\n\n## 📚 Syntax\n\n### Array\n\n```js\n[]\n```\n\n```js\n[1]\n```\n\n```js\n[1,]\n```\n\n```js\n[1, 2]\n```\n\n```js\n[1, 2,]\n```\n\n### Object\n\n```js\n{}\n```\n\n```js\n{ \"foo\": 1 }\n```\n\n```js\n{ \"foo\": 1, }\n```\n\n```js\n{ 'foo': 1, }\n```\n\n```js\n{ `foo`: 1, }\n```\n\n```js\n{ foo: 1, }\n```\n\n```js\n{ \"foo\": 1, \"bar\": 2, }\n```\n\n```js\n{ \"foo\" =\u003e 1 }\n```\n\n```js\n{ \"foo\" = 1 }\n```\n\n```js\n{ foo.bar.baz = 1 }\n// -\u003e { \"foo\": { \"bar\": { \"baz\": 1 } } }\n```\n\n```js\n{ \"foo\".bar.\"baz\" = 1 }\n// -\u003e { \"foo\": { \"bar\": { \"baz\": 1 } } }\n```\n\n### Number\n\n```js\n123\n```\n```js\n-123\n```\n```js\n-123s64\n```\n```js\n123u64\n```\n```js\n-123.45\n```\n```js\n-1.2345e+6\n```\n```js\n-123_456_789\n```\n```js\n-123_456.789_012\n```\n```js\n0x12345678\n```\n```js\n0x1234_5678\n```\n```js\n0o7654_3210\n```\n```js\n0b0101_0101\n```\n```js\n0x1p-2\n```\n```js\n0x1.Fp+0\n```\n```js\n0X_1_FFF_P-16\n```\n```js\nNaN\n```\n```js\nnan\n```\n```js\nInfinity\n```\n```js\n+Infinity\n```\n```js\n-Infinity\n```\n```js\ninf\n```\n```js\n+inf\n```\n```js\n-inf\n```\n\n### Complex\n\n```js\n1.23 - 34.5i\n```\n```js\n1.23e+1 - 34.5e-1i\n```\n```js\n0x1.8p+1 - 0x1.8p-1i\n```\n```js\nNaN-NaNi\n```\n```js\nNaN - NaN_i\n```\n```js\nInfinity-Infinityi\n```\n```js\nInfinity - Infinity_i\n```\n\n### String\n\n```js\n\"foobar\"\n```\n```js\n'foobar'\n```\n```js\n`foo\nbar`\n```\n```yaml\n\"\"\"foo\nbar\"\"\"\n```\n```yaml\n'''foo\nbar'''\n```\n```js\n\"Hello\\n\\r\\v\\t\\b\\fWorld!\"\n```\n```js\n\"\\u0048\\u0065\\u006c\\u006c\\u006f\\u002c\\u0020\\u0057\\u006f\\u0072\\u006c\\u0064\\u0021\"\n```\n```js\n\"\\u{000048}\\u{000065}\\u{00006c}\\u{00006c}\\u{00006f}\\u{00002c}\\u{000020}\\u{000057}\\u{00006f}\\u{000072}\\u{00006c}\\u{000064}\\u{000021}\"\n```\n```js\n\"\\x48\\x65\\x6c\\x6c\\x6f\\x2c\\x20\\x57\\x6f\\x72\\x6c\\x64\\x21\"\n```\n\n```js\n\"foo\" \"bar\"\n// -\u003e \"foobar\"\n```\n```js\n'foo' 'bar'\n// -\u003e 'foobar'\n```\n\n### Boolean\n\n```js\ntrue\n```\n```js\nfalse\n```\n\n### Null, Undefined\n\n```js\nnull\n// -\u003e nil\n```\n```js\nundefined\n// -\u003e nil\n```\n```rust\nNone\n// -\u003e nil\n```\n\n### Comment\n\n```sh\n# Hash line comment\n```\n```js\n// Line comment\n```\n```js\n/*\n   Block comment\n*/\n```\n\n## ⚖️ License\n\nMIT  \nCopyright (c) 2023 Shellyl_N and Authors.\n\n\n---\nPowered by [takenoco](https://github.com/shellyln/takenoco) Parser Combinator Library\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshellyln%2Fgo-loose-json-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshellyln%2Fgo-loose-json-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshellyln%2Fgo-loose-json-parser/lists"}