From da5548941dd7f0240bd6e2b51e6f419f7f46ad11 Mon Sep 17 00:00:00 2001 From: Sam Park Date: Mon, 2 Mar 2020 11:07:51 -0800 Subject: [PATCH] Add GetString function Resolves #53 Convenience function so users don't have to do: ```go s := string(v.GetStringBytes("key", "a", "b")) ``` --- parser.go | 13 +++++++++++++ parser_example_test.go | 27 +++++++++++++++++++++++++++ parser_test.go | 24 ++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/parser.go b/parser.go index c617835..27a0899 100644 --- a/parser.go +++ b/parser.go @@ -819,6 +819,19 @@ func (v *Value) GetUint64(keys ...string) uint64 { return fastfloat.ParseUint64BestEffort(v.s) } +// GetString returns the string value by the given keys path. +// +// Array indexes may be represented as decimal numbers in keys. +// +// "" is returned for non-existing keys path or for invalid value type. +func (v *Value) GetString(keys ...string) string { + v = v.Get(keys...) + if v == nil || v.Type() != TypeString { + return "" + } + return v.s +} + // GetStringBytes returns string value by the given keys path. // // Array indexes may be represented as decimal numbers in keys. diff --git a/parser_example_test.go b/parser_example_test.go index 6e2ed7a..1188bb4 100644 --- a/parser_example_test.go +++ b/parser_example_test.go @@ -91,6 +91,9 @@ func ExampleValue_Get() { vv := v.Get("foo", "0", "bar", "x") fmt.Printf("foo[0].bar.x=%s\n", vv.GetStringBytes()) + vv = v.Get("foo", "0", "bar", "x") + fmt.Printf("foo[0].bar.x=%s\n", vv.GetString()) + vv = v.Get("qwe") fmt.Printf("qwe=%v\n", vv.GetBool()) @@ -106,6 +109,7 @@ func ExampleValue_Get() { // Output: // foo[0].bar.x=434 + // foo[0].bar.x=434 // qwe=true // foo[1]=[null,false] // foo[1][1]=false @@ -181,6 +185,29 @@ func ExampleObject_Visit() { // string "foobar" } +func ExampleValue_GetString() { + s := `[ + {"foo": "bar"}, + [123, "baz"] + ]` + + var p fastjson.Parser + v, err := p.Parse(s) + if err != nil { + log.Fatalf("cannot parse json: %s", err) + } + fmt.Printf("v[0].foo = %q\n", v.GetString("0", "foo")) + fmt.Printf("v[1][1] = %q\n", v.GetString("1", "1")) + fmt.Printf("v[1][0] = %q\n", v.GetString("1", "0")) + fmt.Printf("v.foo.bar.baz = %q\n", v.GetString("foo", "bar", "baz")) + + // Output: + // v[0].foo = "bar" + // v[1][1] = "baz" + // v[1][0] = "" + // v.foo.bar.baz = "" +} + func ExampleValue_GetStringBytes() { s := `[ {"foo": "bar"}, diff --git a/parser_test.go b/parser_test.go index 771898a..3b57b69 100644 --- a/parser_test.go +++ b/parser_test.go @@ -372,6 +372,14 @@ func TestValueGetTyped(t *testing.T) { if sb != nil { t.Fatalf("unexpected value; got %q; want %q", sb, []byte(nil)) } + s := v.GetString("bar") + if s != "433" { + t.Fatalf("unexpected value; got %q; want %q", s, "443") + } + s = v.GetString("foo") + if s != "" { + t.Fatalf("unexpected value; got %q; want \"\"", s) + } bv := v.GetBool("baz") if !bv { t.Fatalf("unexpected value; got %v; want %v", bv, true) @@ -460,6 +468,14 @@ func TestValueGet(t *testing.T) { if string(sb) != "" { t.Fatalf("unexpected non-empty value: %q", sb) } + s := v.GetString("") + if s != "empty-key" { + t.Fatalf("unexpected value for empty key; got %q; want %q", s, "empty-key") + } + s = v.GetString("empty-value") + if s != "" { + t.Fatalf("unexpected non-empty value: %q", s) + } vv := v.Get("foo", "1") if vv == nil { @@ -545,6 +561,10 @@ func TestParserParse(t *testing.T) { if string(sb) != `\fЗУ\\` { t.Fatalf("unexpected string; got %q; want %q", sb, `\fЗУ\\`) } + s := v.GetString("\\\"\u1234x") + if s != `\fЗУ\\` { + t.Fatalf("unexpected string; got %q; want %q", s, `\fЗУ\\`) + } }) t.Run("invalid-string-escape", func(t *testing.T) { @@ -666,6 +686,10 @@ func TestParserParse(t *testing.T) { if string(sb) != `{"foo": 123}` { t.Fatalf("unexpected string value; got %q; want %q", sb, `{"foo": 123}`) } + s := v.GetString() + if s != `{"foo": 123}` { + t.Fatalf("unexpected string value; got %q; want %q", s, `{"foo": 123}`) + } }) t.Run("incomplete-object", func(t *testing.T) {