Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c9428ca
Add Go implementation using latest jsonic, follow ini/csv patterns
claude Apr 13, 2026
61d2d53
Restructure to match ini/csv patterns, move options into grammar
claude Apr 14, 2026
1c9d00f
Remove redundant programmatic val rule, move options into grammar
claude Apr 14, 2026
2ef8d89
Use @funcref for number.exclude, apply grammar via Grammar()
claude Apr 14, 2026
59cf223
Use regexp.MustCompile for number.exclude funcref
claude Apr 14, 2026
fe8099c
Update jsonic to latest main branch (d883f8681563)
claude Apr 14, 2026
f985095
Move options handled by MapToOptions out of Make() into Grammar
claude Apr 14, 2026
2bdd1cc
Use @/regexp/ for number.exclude in grammar, common to TS and Go
claude Apr 14, 2026
ac3372a
Mirror TS pattern: Make() minimal, plugin applies grammar + SetOptions
claude Apr 14, 2026
e647909
Remove grammar conversion boilerplate, mirror TS code structure
claude Apr 14, 2026
f563840
Update jsonic to 7723d00e04a9, remove custom value matcher
claude Apr 14, 2026
9d442ff
Use GrammarText for Go, simplify TS grammar call
claude Apr 14, 2026
7201fe0
Update jsonic to fc840a706389, simplify Go plugin with GrammarText
claude Apr 14, 2026
028fb39
Update jsonic to a7123a89416f
claude Apr 14, 2026
39773ca
Update jsonic to 6cf502bdab73 — all tests pass
claude Apr 14, 2026
9b5adb7
Update jsonc.ts
rjrodger Apr 14, 2026
be7dac4
Simplify Go plugin to mirror TS code structure
claude Apr 14, 2026
db588b2
Remove Parse/MakeJsonic/JsoncOptions wrappers, export only Jsonc plugin
claude Apr 14, 2026
7142156
Update jsonic to 658b8423f645, trailing commas in grammar, return errors
claude Apr 14, 2026
d99d309
Update jsonic to 11271873799c, Jsonc now usable via j.Use(Jsonc)
claude Apr 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 25 additions & 13 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions

name: build

on:
Expand All @@ -16,23 +13,38 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [14.x, 16.x, 18.x, 20.x]
node-version: [24.x]

runs-on: ${{ matrix.os }}

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm i
- run: npm run build --if-present
- run: npm test

- name: Coveralls
uses: coverallsapp/github-action@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./coverage/lcov.info
build-go:

strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]

runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.24'
- name: Build
working-directory: go
run: go build ./...
- name: Test
working-directory: go
run: go test -v ./...
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,12 @@ test/coverage.html

coverage

dist
dist-test
*.tsbuildinfo

package-lock.json
yarn.lock

# Go
go/vendor/
53 changes: 53 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.PHONY: all build test clean build-ts build-go test-ts test-go clean-ts clean-go publish-go tags-go tidy-go reset

all: build test

build: build-ts build-go

test: test-ts test-go

clean: clean-ts clean-go

# TypeScript
build-ts:
npm run build

test-ts:
npm test

clean-ts:
rm -rf dist dist-test

# Go
build-go:
cd go && go build ./...

test-go:
cd go && go test ./...

clean-go:
cd go && go clean -cache

# Publish Go module: make publish-go V=0.1.1
publish-go: test-go
@test -n "$(V)" || (echo "Usage: make publish-go V=x.y.z" && exit 1)
git add go/jsonc.go
git commit -m "go: v$(V)"
git tag go/v$(V)
git push origin main go/v$(V)
if command -v gh >/dev/null 2>&1; then gh release create go/v$(V) --title "go/v$(V)" --notes "Go module release v$(V)"; fi

tidy-go:
cd go && go mod tidy

tags-go:
git tag -l 'go/v*' --sort=-version:refname

reset:
rm -rf dist node_modules package-lock.json
npm install
npm run build
npm test
cd go && go clean -cache
cd go && go build ./...
cd go && go test -v ./...
133 changes: 124 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,143 @@
# @jsonic/jsonc (JSONIC variant plugin)
# @jsonic/jsonc

This plugin allows the [Jsonic](https://jsonic.senecajs.org) JSON parser
to parse [JSONC](https://github.com/microsoft/node-jsonc-parser) format files.

to parse [JSONC](https://github.com/microsoft/node-jsonc-parser) format
files (JSON with Comments).

JSONC is a strict superset of JSON that adds single-line (`//`) and
block (`/* */`) comments. Trailing commas in objects and arrays can be
optionally enabled.

[![npm version](https://img.shields.io/npm/v/@jsonic/jsonc.svg)](https://npmjs.com/package/@jsonic/jsonc)
[![build](https://github.com/jsonicjs/jsonc/actions/workflows/build.yml/badge.svg)](https://github.com/jsonicjs/jsonc/actions/workflows/build.yml)
[![Coverage Status](https://coveralls.io/repos/github/jsonicjs/jsonc/badge.svg?branch=main)](https://coveralls.io/github/jsonicjs/jsonc?branch=main)
[![Known Vulnerabilities](https://snyk.io/test/github/jsonicjs/jsonc/badge.svg)](https://snyk.io/test/github/jsonicjs/jsonc)
[![DeepScan grade](https://deepscan.io/api/teams/5016/projects/25267/branches/788638/badge/grade.svg)](https://deepscan.io/dashboard#view=project&tid=5016&pid=25267&bid=788638)
[![Maintainability](https://api.codeclimate.com/v1/badges/6da148ebd83e336cdcbe/maintainability)](https://codeclimate.com/github/jsonicjs/jsonc/maintainability)


| ![Voxgig](https://www.voxgig.com/res/img/vgt01r.png) | This open source module is sponsored and supported by [Voxgig](https://www.voxgig.com). |
| ---------------------------------------------------- | --------------------------------------------------------------------------------------- |


## Features

- Single-line comments: `// comment`
- Block comments: `/* comment */`
- Optional trailing commas in objects and arrays
- Strict JSON value parsing (no unquoted strings or hex numbers)
- Available in both TypeScript/JavaScript and Go


## TypeScript

### Install

```bash
npm install @jsonic/jsonc @jsonic/jsonic-next
```

### Quick Start

```typescript
import { Jsonic } from '@jsonic/jsonic-next'
import { Jsonc } from '@jsonic/jsonc'

const j = Jsonic.make().use(Jsonc)

// Parse JSONC with comments
const result = j('{ "name": "app", /* version */ "version": "1.0" }')
// => { name: "app", version: "1.0" }

// Enable trailing commas
const jc = Jsonic.make().use(Jsonc, { allowTrailingComma: true })
const config = jc('{ "debug": true, "verbose": false, }')
// => { debug: true, verbose: false }
```

### Options

| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `allowTrailingComma` | `boolean` | `false` | Allow trailing commas in objects and arrays |
| `disallowComments` | `boolean` | `false` | Disable comment parsing (strict JSON mode) |


## Go

### Install

```bash
go get github.com/jsonicjs/jsonc/go
```

### Quick Start

```go
package main

import (
"fmt"
jsonc "github.com/jsonicjs/jsonc/go"
)

func main() {
// Parse JSONC with comments
result, err := jsonc.Parse(`{ "name": "app", /* version */ "version": "1.0" }`)
if err != nil {
panic(err)
}
fmt.Println(result)
// => map[name:app version:1.0]

// Enable trailing commas
result, err = jsonc.Parse(
`{ "debug": true, "verbose": false, }`,
jsonc.JsoncOptions{AllowTrailingComma: boolPtr(true)},
)
fmt.Println(result)
// => map[debug:true verbose:false]
}

func boolPtr(b bool) *bool { return &b }
```

### API

#### `Parse(src string, opts ...JsoncOptions) (any, error)`

Parse a JSONC string and return the result. Returns `map[string]any` for
objects, `[]any` for arrays, `float64` for numbers, `string`, `bool`,
or `nil`.

#### `MakeJsonic(opts ...JsoncOptions) *jsonic.Jsonic`

Create a configured jsonic instance for JSONC parsing. Use this when you
need to parse multiple inputs with the same configuration.

#### `JsoncOptions`

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `AllowTrailingComma` | `*bool` | `false` | Allow trailing commas in objects and arrays |
| `DisallowComments` | `*bool` | `false` | Disable comment parsing |


## JSONC Format

JSONC follows [RFC 8259](https://tools.ietf.org/html/rfc8259) (JSON) with
these extensions:

<!--START:options-->
## Options
_None_
<!--END:options-->
- **Line comments**: `//` to end of line
- **Block comments**: `/* */` (non-nesting)
- **Trailing commas**: optional, in objects and arrays

All other rules follow standard JSON:
- Strings must be double-quoted
- Only standard escape sequences: `\"` `\\` `\/` `\b` `\f` `\n` `\r` `\t` `\uXXXX`
- Numbers: integer, decimal, scientific notation (no hex, octal, or binary)
- Keywords: `true`, `false`, `null` (case-sensitive)
- Property names must be double-quoted strings


## License

MIT. Copyright (c) 2021-2025 Richard Rodger and contributors.
74 changes: 74 additions & 0 deletions embed-grammar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env node

// Embed jsonc-grammar.jsonic into TypeScript and Go source files.
// Run via: npm run embed (or: node embed-grammar.js)

const fs = require('fs')
const path = require('path')

const GRAMMAR_FILE = path.join(__dirname, 'jsonc-grammar.jsonic')
const TS_FILE = path.join(__dirname, 'src', 'jsonc.ts')
const GO_FILE = path.join(__dirname, 'go', 'jsonc.go')

const BEGIN = '// --- BEGIN EMBEDDED jsonc-grammar.jsonic ---'
const END = '// --- END EMBEDDED jsonc-grammar.jsonic ---'

const grammar = fs.readFileSync(GRAMMAR_FILE, 'utf8')

// --- TypeScript embedding ---
function embedTS() {
let src = fs.readFileSync(TS_FILE, 'utf8')
const startIdx = src.indexOf(BEGIN)
const endIdx = src.indexOf(END)
if (startIdx === -1 || endIdx === -1) {
console.error('TS markers not found in', TS_FILE)
process.exit(1)
}

// Escape backticks and template expressions for a JS template literal.
const escaped = grammar
.replace(/\\/g, '\\\\')
.replace(/`/g, '\\`')
.replace(/\$\{/g, '\\${')

const replacement =
BEGIN +
'\nconst grammarText = `\n' +
escaped +
'`\n' +
END

src = src.substring(0, startIdx) + replacement + src.substring(endIdx + END.length)
fs.writeFileSync(TS_FILE, src)
console.log('Embedded grammar into', TS_FILE)
}

// --- Go embedding ---
function embedGo() {
let src = fs.readFileSync(GO_FILE, 'utf8')
const startIdx = src.indexOf(BEGIN)
const endIdx = src.indexOf(END)
if (startIdx === -1 || endIdx === -1) {
console.error('Go markers not found in', GO_FILE)
process.exit(1)
}

if (grammar.includes('`')) {
console.error('Grammar contains backticks, incompatible with Go raw strings')
process.exit(1)
}

const replacement =
BEGIN +
'\nconst grammarText = `\n' +
grammar +
'`\n' +
END

src = src.substring(0, startIdx) + replacement + src.substring(endIdx + END.length)
fs.writeFileSync(GO_FILE, src)
console.log('Embedded grammar into', GO_FILE)
}

embedTS()
embedGo()
5 changes: 5 additions & 0 deletions go/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module github.com/jsonicjs/jsonc/go

go 1.24.7

require github.com/jsonicjs/jsonic/go v0.1.16-0.20260414173219-11271873799c
10 changes: 10 additions & 0 deletions go/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414152106-fc840a706389 h1:ieVCIYU0//FXYcRfCXbIl0nDonTNdh7yYbnXLfCaaVY=
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414152106-fc840a706389/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414154112-a7123a89416f h1:Cm5qVNBZ2HX6ytlmVLETnFs04Q8gmCzXXmM41nO0tHs=
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414154112-a7123a89416f/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414154952-6cf502bdab73 h1:0wr2ga68Bv+WvVKCdh5JZ4UbIqNC8sNi1BReCpBil+I=
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414154952-6cf502bdab73/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414171226-658b8423f645 h1:dpnkbPb+PFJyTJekQ3kFZdje8Vc75nH3dZSeVciqw64=
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414171226-658b8423f645/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414173219-11271873799c h1:NMy6WDlgAoN18lvmyDet9DVBEXrmc209fFg34ABm/hw=
github.com/jsonicjs/jsonic/go v0.1.16-0.20260414173219-11271873799c/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg=
Loading
Loading