Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/getify/JSON.minify/tree/go

go 1.18
92 changes: 92 additions & 0 deletions minify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package minify

import (
"strings"
)

func JsonMinify(json string, stripSpace bool) string {
var out strings.Builder
indexMultilineComment := -1
indexInlineComment := -1
inJsonStr := false
skip := false
for i, r := range json {
if skip {
skip = false
continue
}
switch r {
case '/':
if !inJsonStr && indexMultilineComment == -1 && indexInlineComment == -1 {
// if currently not in a comment or json string, a slash
// could be the beginning of a new comment. look ahead and see
if len(json) > i+1 {
if json[i+1] == '/' {
indexInlineComment = i
// since we already looked ahead, we don't need
// to consider the next character
skip = true
} else if json[i+1] == '*' {
indexMultilineComment = i
// since we already looked ahead, we don't need
// to consider the next character
skip = true
}
}
}
case '*':
if indexMultilineComment != -1 {
// we are currently in a multiline comment. A star sign could mean
// the end of our multiline comment. look ahead and see
if len(json) > i+1 {
if json[i+1] == '/' {
indexMultilineComment = -1
// since we already looked ahead, we don't need to consider
// the next character
skip = true
// a bit nasty but since we don't want to print the current
// character, we need to skip the rest
continue
}
}
}
case '"':
if inJsonStr {
inJsonStr = false
} else if !inJsonStr && indexMultilineComment == -1 && indexInlineComment == -1 {
// if we are currently not in a comment, a quote sign can only mean
// we got into a JSON string
inJsonStr = true
}
case '\\':
if len(json) > i+1 {
if json[i+1] == '"' {
// next quote sign is escaped and therefore looses it's meaning
// as start/end of JSON string. put into output and skip both
out.WriteRune('\\')
out.WriteRune('"')
skip = true
continue
} else if json[i+1] == '\\' {
// the next escape must loose it's power to escape stuff
// because it itself is escaped
out.WriteRune('\\')
skip = true
}
}
case '\n':
indexInlineComment = -1
case '\r':
indexInlineComment = -1
}
if indexMultilineComment == -1 && indexInlineComment == -1 {
// only consider in output if character is outside of any comment
if !stripSpace || inJsonStr || (r != '\n' && r != '\r' && r != '\t' && r != ' ') {
// everything considered a whitespace (line feed, carriage return, tab, whitespace)
// is only candidate for output if desired
out.WriteRune(r)
}
}
}
return out.String()
}
72 changes: 72 additions & 0 deletions minify_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package minify

import (
"bytes"
"testing"
)

type Test struct {
Before string;
Expected string;
}

func TestRemoveComments(t *testing.T) {
tests := []Test {
{
Before: `
// this is a JSON file with comments
{
"foo": "bar", // this is cool
"bar": [
"baz", "bum", "zam"
],
/* the rest of this document is just fluff
in case you are interested. */
"something": 10,
"else": 20
}

/* NOTE: You can easily strip the whitespace and comments
from such a file with the JSON.minify() project hosted
here on github at http://github.com/getify/JSON.minify
*/`,
Expected: `{"foo":"bar","bar":["baz","bum","zam"],"something":10,"else":20}`,
},
{
Before: `

{"/*":"*/","//":"",/*"//"*/"/*/"://
"//"}
`,
Expected: `{"/*":"*/","//":"","/*/":"//"}`,
},
{
Before: `
/*
this is a
multi line comment */{

"foo"
:
"bar/*"// something
, "b\\\"az":/*
something else */"blah"

}`,
Expected: `{"foo":"bar/*","b\\\"az":"blah"}`,
},
{
Before: `
{"foo": "ba\\\"r//", "bar\\\\": "b\\\\\\\"a/*z",
"baz\\\\\\\\": /* yay */ "fo\\\\\\\\\\\"*/o"
}`,
Expected: `{"foo":"ba\\\"r//","bar\\\\":"b\\\\\\\"a/*z","baz\\\\\\\\":"fo\\\\\\\\\\\"*/o"}`,
}};

for _, test := range tests {
after := JsonMinify(test.Before, true)
if !bytes.Equal([]byte(after), []byte(test.Expected)) {
t.Fatalf("Not the same:\nreal: %s\nExpected:%s\n", after, test.Expected)
}
}
}