Experiment with parsing json

This commit is contained in:
Ian Wahbe 2021-11-08 18:13:05 -08:00
parent afcbcd3a51
commit bfc6df303e
4 changed files with 131 additions and 0 deletions

View file

@ -84,6 +84,7 @@ require (
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/alecthomas/participle/v2 v2.0.0-alpha7 // indirect
github.com/apparentlymart/go-textseg v1.0.0 // indirect
github.com/cheggaaa/pb v1.0.18 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect

View file

@ -112,6 +112,9 @@ github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tj
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs=
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c=
github.com/alecthomas/participle/v2 v2.0.0-alpha7/go.mod h1:NumScqsC42o9x+dGj8/YqsIfhrIQjFEOFovxotbBirA=
github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=

116
pkg/util/parsing/json.go Normal file
View file

@ -0,0 +1,116 @@
package parsing
import (
"fmt"
"github.com/alecthomas/participle/v2"
"github.com/alecthomas/participle/v2/lexer"
)
type Value struct {
Object *Object ` @@`
Array *Array `| @@`
String_ *string `| @String`
Number *Number `| @@`
Null *bool `| "null"`
Bool *bool `| (@"true" | "false")`
}
func (v *Value) String() string {
switch {
case v.Object != nil:
return v.Object.String()
case v.Array != nil:
return v.Array.String()
case v.String_ != nil:
return *v.String_
case v.Number != nil:
return v.Number.String()
case v.Null != nil:
return "null"
case v.Bool != nil:
if *v.Bool {
return "true"
}
return "false"
default:
panic("Value not initialized")
}
}
type Object struct {
Members []*Member `"{" ( @@ ( "," @@ )* )? "}"`
}
func (o *Object) String() string {
if len(o.Members) == 0 {
return "{ }"
}
s := "{ " + o.Members[0].String()
for i := 1; i < len(o.Members); i++ {
s = s + ", " + o.Members[i].String()
}
return s + " }"
}
type Member struct {
Key *string `@String ":"`
Value *Value `@@`
}
func (m Member) String() string {
return *m.Key + ": " + (*m.Value).String()
}
type Array struct {
Entries []*Value `"[" ( @@ ( "," @@ )* )? "]"`
}
func (a Array) String() string {
if len(a.Entries) == 0 {
return "[ ]"
}
s := "[ " + a.Entries[0].String()
for i := 1; i < len(a.Entries); i++ {
s = s + ", " + a.Entries[i].String()
}
return s + " ]"
}
type Number struct {
Integer *Integer `@@`
Fraction *Fraction `@@`
Exponent *Exponent `@@`
}
type Integer struct {
Minus *char `@"-"`
digit *string `@Digit`
rest *string `@OneNine`
}
func (n Number) String() string {
return *n.Integer
}
func ParseJSON(s string) {
jsonLexer := lexer.Must(lexer.NewSimple([]lexer.Rule{
{"Digit", `[0-9]`, nil},
{"OneNine", `[1-9]`, nil},
{"whitespace", `\s+`, nil},
{"String", `"[^"]*"`, nil},
{"Punct", `[\{\}\[\],:]`, nil},
{"Null", "null", nil},
{"Bool", "true|false", nil},
}))
jsonParser := participle.MustBuild(&Value{}, participle.Lexer(jsonLexer), participle.Unquote("String"))
json := &Value{}
err := jsonParser.ParseString("schema", s, json)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Printf("JSON parsed to %v\n", json)
}
}

View file

@ -0,0 +1,11 @@
package parsing
import (
"testing"
)
func TestJsonParsing(t *testing.T) {
s := `{ "jo" : 89, "phinues": "pherb"}`
ParseJSON(s)
t.FailNow()
}