From bfc6df303e90a9f84740baa71960f466983b2821 Mon Sep 17 00:00:00 2001 From: Ian Wahbe Date: Mon, 8 Nov 2021 18:13:05 -0800 Subject: [PATCH] Experiment with parsing json --- pkg/go.mod | 1 + pkg/go.sum | 3 + pkg/util/parsing/json.go | 116 ++++++++++++++++++++++++++++++++++ pkg/util/parsing/json_test.go | 11 ++++ 4 files changed, 131 insertions(+) create mode 100644 pkg/util/parsing/json.go create mode 100644 pkg/util/parsing/json_test.go diff --git a/pkg/go.mod b/pkg/go.mod index f7c215450..9ee9cc3e2 100644 --- a/pkg/go.mod +++ b/pkg/go.mod @@ -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 diff --git a/pkg/go.sum b/pkg/go.sum index d1ace4103..33eb3e7c1 100644 --- a/pkg/go.sum +++ b/pkg/go.sum @@ -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= diff --git a/pkg/util/parsing/json.go b/pkg/util/parsing/json.go new file mode 100644 index 000000000..303e7745a --- /dev/null +++ b/pkg/util/parsing/json.go @@ -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) + } +} diff --git a/pkg/util/parsing/json_test.go b/pkg/util/parsing/json_test.go new file mode 100644 index 000000000..24c187737 --- /dev/null +++ b/pkg/util/parsing/json_test.go @@ -0,0 +1,11 @@ +package parsing + +import ( + "testing" +) + +func TestJsonParsing(t *testing.T) { + s := `{ "jo" : 89, "phinues": "pherb"}` + ParseJSON(s) + t.FailNow() +}