diff options
| author | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
|---|---|---|
| committer | Rob Pike <r@golang.org> | 2009-06-09 09:53:44 -0700 |
| commit | 7249ea4df2b4f12a4e7ed446f270cea87e4ffd34 (patch) | |
| tree | 7032a11d0cac2ae4d3e90f7a189b575b5a50f848 /src/lib/json/generic.go | |
| parent | acf6ef7a82b3fe61516a1bac4563706552bdf078 (diff) | |
| download | golang-7249ea4df2b4f12a4e7ed446f270cea87e4ffd34.tar.gz | |
mv src/lib to src/pkg
tests: all.bash passes, gobuild still works, godoc still works.
R=rsc
OCL=30096
CL=30102
Diffstat (limited to 'src/lib/json/generic.go')
| -rw-r--r-- | src/lib/json/generic.go | 331 |
1 files changed, 0 insertions, 331 deletions
diff --git a/src/lib/json/generic.go b/src/lib/json/generic.go deleted file mode 100644 index e3194eb17..000000000 --- a/src/lib/json/generic.go +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Generic representation of JSON objects. - -package json - -import ( - "container/vector"; - "fmt"; - "json"; - "math"; - "strconv"; - "strings"; -) - -// Integers identifying the data type in the Json interface. -const ( - StringKind = iota; - NumberKind; - MapKind; // JSON term is "Object", but in Go, it's a map - ArrayKind; - BoolKind; - NullKind; -) - -// The Json interface is implemented by all JSON objects. -type Json interface { - Kind() int; // StringKind, NumberKind, etc. - String() string; // a string form (any kind) - Number() float64; // numeric form (NumberKind) - Bool() bool; // boolean (BoolKind) - Get(s string) Json; // field lookup (MapKind) - Elem(i int) Json; // element lookup (ArrayKind) - Len() int; // length (ArrayKind, MapKind) -} - -// JsonToString returns the textual JSON syntax representation -// for the JSON object j. -// -// JsonToString differs from j.String() in the handling -// of string objects. If j represents the string abc, -// j.String() == `abc`, but JsonToString(j) == `"abc"`. -func JsonToString(j Json) string { - if j == nil { - return "null" - } - if j.Kind() == StringKind { - return Quote(j.String()) - } - return j.String() -} - -type _Null struct { } - -// Null is the JSON object representing the null data object. -var Null Json = &_Null{} - -func (*_Null) Kind() int { return NullKind } -func (*_Null) String() string { return "null" } -func (*_Null) Number() float64 { return 0 } -func (*_Null) Bool() bool { return false } -func (*_Null) Get(s string) Json { return Null } -func (*_Null) Elem(int) Json { return Null } -func (*_Null) Len() int { return 0 } - -type _String struct { s string; _Null } -func (j *_String) Kind() int { return StringKind } -func (j *_String) String() string { return j.s } - -type _Number struct { f float64; _Null } -func (j *_Number) Kind() int { return NumberKind } -func (j *_Number) Number() float64 { return j.f } -func (j *_Number) String() string { - if math.Floor(j.f) == j.f { - return fmt.Sprintf("%.0f", j.f); - } - return fmt.Sprintf("%g", j.f); -} - -type _Array struct { a *vector.Vector; _Null } -func (j *_Array) Kind() int { return ArrayKind } -func (j *_Array) Len() int { return j.a.Len() } -func (j *_Array) Elem(i int) Json { - if i < 0 || i >= j.a.Len() { - return Null - } - return j.a.At(i).(Json) -} -func (j *_Array) String() string { - s := "["; - for i := 0; i < j.a.Len(); i++ { - if i > 0 { - s += ","; - } - s += JsonToString(j.a.At(i).(Json)); - } - s += "]"; - return s; -} - -type _Bool struct { b bool; _Null } -func (j *_Bool) Kind() int { return BoolKind } -func (j *_Bool) Bool() bool { return j.b } -func (j *_Bool) String() string { - if j.b { - return "true" - } - return "false" -} - -type _Map struct { m map[string]Json; _Null } -func (j *_Map) Kind() int { return MapKind } -func (j *_Map) Len() int { return len(j.m) } -func (j *_Map) Get(s string) Json { - if j.m == nil { - return Null - } - v, ok := j.m[s]; - if !ok { - return Null - } - return v; -} -func (j *_Map) String() string { - s := "{"; - first := true; - for k,v := range j.m { - if first { - first = false; - } else { - s += ","; - } - s += Quote(k); - s += ":"; - s += JsonToString(v); - } - s += "}"; - return s; -} - -// Walk evaluates path relative to the JSON object j. -// Path is taken as a sequence of slash-separated field names -// or numbers that can be used to index into JSON map and -// array objects. -// -// For example, if j is the JSON object for -// {"abc": [true, false]}, then Walk(j, "abc/1") returns the -// JSON object for true. -func Walk(j Json, path string) Json { - for len(path) > 0 { - var elem string; - if i := strings.Index(path, "/"); i >= 0 { - elem = path[0:i]; - path = path[i+1:len(path)]; - } else { - elem = path; - path = ""; - } - switch j.Kind() { - case ArrayKind: - indx, err := strconv.Atoi(elem); - if err != nil { - return Null - } - j = j.Elem(indx); - case MapKind: - j = j.Get(elem); - default: - return Null - } - } - return j -} - -// Equal returns whether a and b are indistinguishable JSON objects. -func Equal(a, b Json) bool { - switch { - case a == nil && b == nil: - return true; - case a == nil || b == nil: - return false; - case a.Kind() != b.Kind(): - return false; - } - - switch a.Kind() { - case NullKind: - return true; - case StringKind: - return a.String() == b.String(); - case NumberKind: - return a.Number() == b.Number(); - case BoolKind: - return a.Bool() == b.Bool(); - case ArrayKind: - if a.Len() != b.Len() { - return false; - } - for i := 0; i < a.Len(); i++ { - if !Equal(a.Elem(i), b.Elem(i)) { - return false; - } - } - return true; - case MapKind: - m := a.(*_Map).m; - if len(m) != len(b.(*_Map).m) { - return false; - } - for k,v := range m { - if !Equal(v, b.Get(k)) { - return false; - } - } - return true; - } - - // invalid kind - return false; -} - - -// Parse builder for JSON objects. - -type _JsonBuilder struct { - // either writing to *ptr - ptr *Json; - - // or to a[i] (can't set ptr = &a[i]) - a *vector.Vector; - i int; - - // or to m[k] (can't set ptr = &m[k]) - m map[string] Json; - k string; -} - -func (b *_JsonBuilder) Put(j Json) { - switch { - case b.ptr != nil: - *b.ptr = j; - case b.a != nil: - b.a.Set(b.i, j); - case b.m != nil: - b.m[b.k] = j; - } -} - -func (b *_JsonBuilder) Get() Json { - switch { - case b.ptr != nil: - return *b.ptr; - case b.a != nil: - return b.a.At(b.i).(Json); - case b.m != nil: - return b.m[b.k]; - } - return nil -} - -func (b *_JsonBuilder) Float64(f float64) { - b.Put(&_Number{f, _Null{}}) -} - -func (b *_JsonBuilder) Int64(i int64) { - b.Float64(float64(i)) -} - -func (b *_JsonBuilder) Uint64(i uint64) { - b.Float64(float64(i)) -} - -func (b *_JsonBuilder) Bool(tf bool) { - b.Put(&_Bool{tf, _Null{}}) -} - -func (b *_JsonBuilder) Null() { - b.Put(Null) -} - -func (b *_JsonBuilder) String(s string) { - b.Put(&_String{s, _Null{}}) -} - - -func (b *_JsonBuilder) Array() { - b.Put(&_Array{vector.New(0), _Null{}}) -} - -func (b *_JsonBuilder) Map() { - b.Put(&_Map{make(map[string]Json), _Null{}}) -} - -func (b *_JsonBuilder) Elem(i int) Builder { - bb := new(_JsonBuilder); - bb.a = b.Get().(*_Array).a; - bb.i = i; - for i >= bb.a.Len() { - bb.a.Push(Null) - } - return bb -} - -func (b *_JsonBuilder) Key(k string) Builder { - bb := new(_JsonBuilder); - bb.m = b.Get().(*_Map).m; - bb.k = k; - bb.m[k] = Null; - return bb -} - -// StringToJson parses the string s as a JSON-syntax string -// and returns the generic JSON object representation. -// On success, StringToJson returns with ok set to true and errtok empty. -// If StringToJson encounters a syntax error, it returns with -// ok set to false and errtok set to a fragment of the offending syntax. -func StringToJson(s string) (json Json, ok bool, errtok string) { - var errindx int; - var j Json; - b := new(_JsonBuilder); - b.ptr = &j; - ok, errindx, errtok = Parse(s, b); - if !ok { - return nil, false, errtok - } - return j, true, "" -} - -// BUG(rsc): StringToJson should return an os.Error instead of a bool. |
