Created
January 6, 2024 23:00
-
-
Save mosajjal/be9fb970940c18f91f8edd97c39702d6 to your computer and use it in GitHub Desktop.
flatten nested json strings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// use: | |
// cat nested.json | go run . > flattenned.json | |
package main | |
import ( | |
"bytes" | |
"compress/gzip" | |
"encoding/base64" | |
"fmt" | |
"io" | |
"log" | |
"os" | |
"testing" | |
"time" | |
"github.com/jeremywohl/flatten/v2" | |
) | |
const ( | |
maxBufferSize = 102400 | |
) | |
func main() { | |
b := make([]byte, 1) | |
c := make(chan byte, 2) | |
fd := os.Stdout | |
go start(c, fd) | |
for { | |
n, err := os.Stdin.Read(b) | |
if err != nil && err != io.EOF { | |
log.Fatal(err) | |
} | |
if n == 0 { | |
// sleep for a bit | |
time.Sleep(100 * time.Millisecond) | |
break | |
} | |
c <- b[0] | |
} | |
} | |
func start(c chan byte, fd io.Writer) { | |
buf := make([]byte, maxBufferSize) | |
openBracket := 0 | |
count := 0 | |
inObject := false | |
// Read stdin into buffer | |
for ch := range c { | |
if ch == '\n' || ch == '\r' || ch == ' ' || ch == '\t' { | |
continue | |
} | |
if ch == '{' { | |
openBracket++ | |
inObject = true | |
} | |
if ch == '}' { | |
openBracket-- | |
} | |
if !inObject && (ch == '[' || ch == ']') { | |
continue | |
} | |
if ch == ',' && !inObject { | |
continue | |
} | |
buf[count] = ch | |
count++ | |
if openBracket == 0 && inObject { | |
// flatten buffer and print | |
flat, err := flatten.FlattenString(string(buf[:count]), "", flatten.DotStyle) | |
if err != nil { | |
log.Println(err, string(buf[:count])) | |
} | |
fmt.Fprintln(fd, flat) | |
buf = make([]byte, maxBufferSize) | |
inObject = false | |
count = 0 | |
} | |
} | |
} | |
var testJSON1BB64GZ = "H4sIAAAAAAACA+2QvQ6CQBCE+3uKzdZQiD+FNdHEwgasCMUBK7fJcZfAUhDiu3tijIWFPoBbbPPtzGammJGHyuEecJWs4812FydJghGAAtSjGN8HpiDMvGwAtHoQpzt6iFJPGL3Alfs3OWlHuJBbpJAali9WWcdifjELUFjsAnJDcLHCnRaCVIuu9ECQydhMcBy5oWcUwDoctL6fgqjAs3fxgWth7wLHnGrjvPXthKUKH/6dfHRSqjuB6mvcKgIAAA==" | |
func gzipDecode(data []byte) ([]byte, error) { | |
gz, err := gzip.NewReader(bytes.NewReader(data)) | |
if err != nil { | |
return nil, err | |
} | |
defer gz.Close() | |
return io.ReadAll(gz) | |
} | |
func BenchmarkMain(b *testing.B) { | |
//un-base64 and un-gzip the test data | |
testJSON1B, _ := base64.StdEncoding.DecodeString(testJSON1BB64GZ) | |
testJSON1B, _ = gzipDecode(testJSON1B) | |
c := make(chan byte) | |
go func() { | |
for _, ch := range testJSON1B { | |
c <- ch | |
} | |
close(c) | |
}() | |
nullOut := io.Discard | |
for i := 0; i < b.N; i++ { | |
start(c, nullOut) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment