diff --git a/go.mod b/go.mod index f948381..50338c7 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/tidwall/jsonc -go 1.16 +go 1.18 diff --git a/jsonc.go b/jsonc.go index c30ff12..a49d4dc 100644 --- a/jsonc.go +++ b/jsonc.go @@ -1,5 +1,9 @@ package jsonc +import ( + "encoding/json" +) + // ToJSON strips out comments and trailing commas and convert the input to a // valid JSON per the official spec: https://tools.ietf.org/html/rfc8259 // @@ -11,6 +15,21 @@ func ToJSON(src []byte) []byte { return toJSON(src, nil) } +// Unmarshal parses the JSONC data and stores the result in the value pointed +// to by v. It is a drop-in replacement for json.Unmarshal from encoding/json. +// +// Unmarshal supports comments (both // and /* */) and trailing commas. +func Unmarshal(data []byte, v any) error { + cleaned := ToJSON(data) + return json.Unmarshal(cleaned, v) +} + +// Marshal returns the JSON encoding of v. It is a drop-in replacement for +// json.Marshal from encoding/json. +func Marshal(v any) ([]byte, error) { + return json.Marshal(v) +} + // ToJSONInPlace is the same as ToJSON, but this method reuses the input json // buffer to avoid allocations. Do not use the original bytes slice upon return. func ToJSONInPlace(src []byte) []byte { diff --git a/jsonc_test.go b/jsonc_test.go index 09e7dcc..dfeb3c5 100644 --- a/jsonc_test.go +++ b/jsonc_test.go @@ -2,6 +2,27 @@ package jsonc import "testing" +func TestUnmarshal(t *testing.T) { + type Person struct { + Name string `json:"name"` + } + + jsonc := `{ + // This is a comment + "name": "John", + }` + + want := Person{Name: "John"} + var got Person + err := Unmarshal([]byte(jsonc), &got) + if err != nil { + t.Fatalf("Unmarshal() error = %v", err) + } + if got != want { + t.Errorf("Unmarshal() got = %v, want %v", got, want) + } +} + func TestToJSON(t *testing.T) { json := ` { // hello