Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
G
golang
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
go
golang
Commits
b7215331
Commit
b7215331
authored
Nov 01, 2009
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
allow unpacking of json map into Go map,
now that reflection supports it. R=r
http://go/go-review/1015008
parent
bf991bb7
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
111 additions
and
47 deletions
+111
-47
generic.go
src/pkg/json/generic.go
+3
-0
parse.go
src/pkg/json/parse.go
+4
-0
struct.go
src/pkg/json/struct.go
+52
-18
struct_test.go
src/pkg/json/struct_test.go
+52
-29
No files found.
src/pkg/json/generic.go
View file @
b7215331
...
...
@@ -364,6 +364,9 @@ func (b *_JsonBuilder) Key(k string) Builder {
return
bb
;
}
func
(
b
*
_JsonBuilder
)
Flush
()
{
}
// 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.
...
...
src/pkg/json/parse.go
View file @
b7215331
...
...
@@ -296,6 +296,9 @@ type Builder interface {
// Create sub-Builders
Elem
(
i
int
)
Builder
;
Key
(
s
string
)
Builder
;
// Flush changes to parent Builder if necessary.
Flush
();
}
func
parse
(
lex
*
_Lexer
,
build
Builder
)
bool
{
...
...
@@ -392,6 +395,7 @@ Switch:
if
ok
{
lex
.
Next
();
}
build
.
Flush
();
return
ok
;
}
...
...
src/pkg/json/struct.go
View file @
b7215331
...
...
@@ -12,11 +12,15 @@ import (
"strings"
;
)
type
_S
tructBuilder
struct
{
type
s
tructBuilder
struct
{
val
reflect
.
Value
;
// if map_ != nil, write val to map_[key] on each change
map_
*
reflect
.
MapValue
;
key
reflect
.
Value
;
}
var
nobuilder
*
_S
tructBuilder
var
nobuilder
*
s
tructBuilder
func
isfloat
(
v
reflect
.
Value
)
bool
{
switch
v
.
(
type
)
{
...
...
@@ -62,7 +66,18 @@ func setint(v reflect.Value, i int64) {
}
}
func
(
b
*
_StructBuilder
)
Int64
(
i
int64
)
{
// If updating b.val is not enough to update the original,
// copy a changed b.val out to the original.
func
(
b
*
structBuilder
)
Flush
()
{
if
b
==
nil
{
return
;
}
if
b
.
map_
!=
nil
{
b
.
map_
.
SetElem
(
b
.
key
,
b
.
val
);
}
}
func
(
b
*
structBuilder
)
Int64
(
i
int64
)
{
if
b
==
nil
{
return
;
}
...
...
@@ -74,7 +89,7 @@ func (b *_StructBuilder) Int64(i int64) {
}
}
func
(
b
*
_S
tructBuilder
)
Uint64
(
i
uint64
)
{
func
(
b
*
s
tructBuilder
)
Uint64
(
i
uint64
)
{
if
b
==
nil
{
return
;
}
...
...
@@ -86,7 +101,7 @@ func (b *_StructBuilder) Uint64(i uint64) {
}
}
func
(
b
*
_S
tructBuilder
)
Float64
(
f
float64
)
{
func
(
b
*
s
tructBuilder
)
Float64
(
f
float64
)
{
if
b
==
nil
{
return
;
}
...
...
@@ -98,9 +113,9 @@ func (b *_StructBuilder) Float64(f float64) {
}
}
func
(
b
*
_S
tructBuilder
)
Null
()
{}
func
(
b
*
s
tructBuilder
)
Null
()
{}
func
(
b
*
_S
tructBuilder
)
String
(
s
string
)
{
func
(
b
*
s
tructBuilder
)
String
(
s
string
)
{
if
b
==
nil
{
return
;
}
...
...
@@ -109,7 +124,7 @@ func (b *_StructBuilder) String(s string) {
}
}
func
(
b
*
_S
tructBuilder
)
Bool
(
tf
bool
)
{
func
(
b
*
s
tructBuilder
)
Bool
(
tf
bool
)
{
if
b
==
nil
{
return
;
}
...
...
@@ -118,7 +133,7 @@ func (b *_StructBuilder) Bool(tf bool) {
}
}
func
(
b
*
_S
tructBuilder
)
Array
()
{
func
(
b
*
s
tructBuilder
)
Array
()
{
if
b
==
nil
{
return
;
}
...
...
@@ -129,14 +144,14 @@ func (b *_StructBuilder) Array() {
}
}
func
(
b
*
_S
tructBuilder
)
Elem
(
i
int
)
Builder
{
func
(
b
*
s
tructBuilder
)
Elem
(
i
int
)
Builder
{
if
b
==
nil
||
i
<
0
{
return
nobuilder
;
}
switch
v
:=
b
.
val
.
(
type
)
{
case
*
reflect
.
ArrayValue
:
if
i
<
v
.
Len
()
{
return
&
_StructBuilder
{
v
.
Elem
(
i
)};
return
&
structBuilder
{
val
:
v
.
Elem
(
i
)};
}
case
*
reflect
.
SliceValue
:
if
i
>
v
.
Cap
()
{
...
...
@@ -155,36 +170,55 @@ func (b *_StructBuilder) Elem(i int) Builder {
v
.
SetLen
(
i
+
1
);
}
if
i
<
v
.
Len
()
{
return
&
_StructBuilder
{
v
.
Elem
(
i
)};
return
&
structBuilder
{
val
:
v
.
Elem
(
i
)};
}
}
return
nobuilder
;
}
func
(
b
*
_S
tructBuilder
)
Map
()
{
func
(
b
*
s
tructBuilder
)
Map
()
{
if
b
==
nil
{
return
;
}
if
v
,
ok
:=
b
.
val
.
(
*
reflect
.
PtrValue
);
ok
{
if
v
,
ok
:=
b
.
val
.
(
*
reflect
.
PtrValue
);
ok
&&
v
.
IsNil
()
{
if
v
.
IsNil
()
{
v
.
PointTo
(
reflect
.
MakeZero
(
v
.
Type
()
.
(
*
reflect
.
PtrType
)
.
Elem
()));
b
.
Flush
();
}
b
.
map_
=
nil
;
b
.
val
=
v
.
Elem
();
}
if
v
,
ok
:=
b
.
val
.
(
*
reflect
.
MapValue
);
ok
&&
v
.
IsNil
()
{
v
.
Set
(
reflect
.
MakeMap
(
v
.
Type
()
.
(
*
reflect
.
MapType
)));
}
}
func
(
b
*
_S
tructBuilder
)
Key
(
k
string
)
Builder
{
func
(
b
*
s
tructBuilder
)
Key
(
k
string
)
Builder
{
if
b
==
nil
{
return
nobuilder
;
}
if
v
,
ok
:=
reflect
.
Indirect
(
b
.
val
)
.
(
*
reflect
.
StructValue
);
ok
{
switch
v
:=
reflect
.
Indirect
(
b
.
val
)
.
(
type
)
{
case
*
reflect
.
StructValue
:
t
:=
v
.
Type
()
.
(
*
reflect
.
StructType
);
// Case-insensitive field lookup.
k
=
strings
.
ToLower
(
k
);
for
i
:=
0
;
i
<
t
.
NumField
();
i
++
{
if
strings
.
ToLower
(
t
.
Field
(
i
)
.
Name
)
==
k
{
return
&
_StructBuilder
{
v
.
Field
(
i
)};
return
&
structBuilder
{
val
:
v
.
Field
(
i
)};
}
}
case
*
reflect
.
MapValue
:
t
:=
v
.
Type
()
.
(
*
reflect
.
MapType
);
if
t
.
Key
()
!=
reflect
.
Typeof
(
k
)
{
break
;
}
key
:=
reflect
.
NewValue
(
k
);
elem
:=
v
.
Elem
(
key
);
if
elem
==
nil
{
v
.
SetElem
(
key
,
reflect
.
MakeZero
(
t
.
Elem
()));
elem
=
v
.
Elem
(
key
);
}
return
&
structBuilder
{
val
:
elem
,
map_
:
v
,
key
:
key
};
}
return
nobuilder
;
}
...
...
@@ -249,7 +283,7 @@ func (b *_StructBuilder) Key(k string) Builder {
// On a syntax error, it returns with ok set to false and errtok
// set to the offending token.
func
Unmarshal
(
s
string
,
val
interface
{})
(
ok
bool
,
errtok
string
)
{
b
:=
&
_StructBuilder
{
reflect
.
NewValue
(
val
)};
b
:=
&
structBuilder
{
val
:
reflect
.
NewValue
(
val
)};
ok
,
_
,
errtok
=
Parse
(
s
,
b
);
if
!
ok
{
return
false
,
errtok
;
...
...
src/pkg/json/struct_test.go
View file @
b7215331
...
...
@@ -5,10 +5,11 @@
package
json
import
(
"reflect"
;
"testing"
;
)
type
_M
yStruct
struct
{
type
m
yStruct
struct
{
T
bool
;
F
bool
;
S
string
;
...
...
@@ -26,17 +27,36 @@ type _MyStruct struct {
Fl32
float32
;
Fl64
float64
;
A
[]
string
;
My
*
_MyStruct
;
My
*
myStruct
;
Map
map
[
string
][]
int
;
MapStruct
map
[
string
]
myStruct
;
MapPtrStruct
map
[
string
]
*
myStruct
;
}
const
_E
ncoded
=
`{"t":true,"f":false,"s":"abc","i8":1,"i16":2,"i32":3,"i64":4,`
const
e
ncoded
=
`{"t":true,"f":false,"s":"abc","i8":1,"i16":2,"i32":3,"i64":4,`
` "u8":5,"u16":6,"u32":7,"u64":8,`
` "i":-9,"u":10,"bogusfield":"should be ignored",`
` "fl":11.5,"fl32":12.25,"fl64":13.75,`
` "a":["x","y","z"],"my":{"s":"subguy"}}`
` "a":["x","y","z"],"my":{"s":"subguy"},`
`"map":{"k1":[1,2,3],"k2":[],"k3":[3,4]},`
`"mapstruct":{"m1":{"u8":8}},`
`"mapptrstruct":{"m1":{"u8":8}}}`
var
decodedMap
=
map
[
string
][]
int
{
"k1"
:
[]
int
{
1
,
2
,
3
},
"k2"
:
[]
int
{},
"k3"
:
[]
int
{
3
,
4
},
}
var
decodedMapStruct
=
map
[
string
]
myStruct
{
"m1"
:
myStruct
{
U8
:
8
},
}
var
decodedMapPtrStruct
=
map
[
string
]
*
myStruct
{
"m1"
:
&
myStruct
{
U8
:
8
},
}
func
_C
heck
(
t
*
testing
.
T
,
ok
bool
,
name
string
,
v
interface
{})
{
func
c
heck
(
t
*
testing
.
T
,
ok
bool
,
name
string
,
v
interface
{})
{
if
!
ok
{
t
.
Errorf
(
"%s = %v (BAD)"
,
name
,
v
);
}
else
{
...
...
@@ -45,36 +65,39 @@ func _Check(t *testing.T, ok bool, name string, v interface{}) {
}
func
TestUnmarshal
(
t
*
testing
.
T
)
{
var
m
_M
yStruct
;
var
m
m
yStruct
;
m
.
F
=
true
;
ok
,
errtok
:=
Unmarshal
(
_E
ncoded
,
&
m
);
ok
,
errtok
:=
Unmarshal
(
e
ncoded
,
&
m
);
if
!
ok
{
t
.
Fatalf
(
"Unmarshal failed near %s"
,
errtok
);
}
_C
heck
(
t
,
m
.
T
==
true
,
"t"
,
m
.
T
);
_C
heck
(
t
,
m
.
F
==
false
,
"f"
,
m
.
F
);
_C
heck
(
t
,
m
.
S
==
"abc"
,
"s"
,
m
.
S
);
_C
heck
(
t
,
m
.
I8
==
1
,
"i8"
,
m
.
I8
);
_C
heck
(
t
,
m
.
I16
==
2
,
"i16"
,
m
.
I16
);
_C
heck
(
t
,
m
.
I32
==
3
,
"i32"
,
m
.
I32
);
_C
heck
(
t
,
m
.
I64
==
4
,
"i64"
,
m
.
I64
);
_C
heck
(
t
,
m
.
U8
==
5
,
"u8"
,
m
.
U8
);
_C
heck
(
t
,
m
.
U16
==
6
,
"u16"
,
m
.
U16
);
_C
heck
(
t
,
m
.
U32
==
7
,
"u32"
,
m
.
U32
);
_C
heck
(
t
,
m
.
U64
==
8
,
"u64"
,
m
.
U64
);
_C
heck
(
t
,
m
.
I
==
-
9
,
"i"
,
m
.
I
);
_C
heck
(
t
,
m
.
U
==
10
,
"u"
,
m
.
U
);
_C
heck
(
t
,
m
.
Fl
==
11.5
,
"fl"
,
m
.
Fl
);
_C
heck
(
t
,
m
.
Fl32
==
12.25
,
"fl32"
,
m
.
Fl32
);
_C
heck
(
t
,
m
.
Fl64
==
13.75
,
"fl64"
,
m
.
Fl64
);
_C
heck
(
t
,
m
.
A
!=
nil
,
"a"
,
m
.
A
);
c
heck
(
t
,
m
.
T
==
true
,
"t"
,
m
.
T
);
c
heck
(
t
,
m
.
F
==
false
,
"f"
,
m
.
F
);
c
heck
(
t
,
m
.
S
==
"abc"
,
"s"
,
m
.
S
);
c
heck
(
t
,
m
.
I8
==
1
,
"i8"
,
m
.
I8
);
c
heck
(
t
,
m
.
I16
==
2
,
"i16"
,
m
.
I16
);
c
heck
(
t
,
m
.
I32
==
3
,
"i32"
,
m
.
I32
);
c
heck
(
t
,
m
.
I64
==
4
,
"i64"
,
m
.
I64
);
c
heck
(
t
,
m
.
U8
==
5
,
"u8"
,
m
.
U8
);
c
heck
(
t
,
m
.
U16
==
6
,
"u16"
,
m
.
U16
);
c
heck
(
t
,
m
.
U32
==
7
,
"u32"
,
m
.
U32
);
c
heck
(
t
,
m
.
U64
==
8
,
"u64"
,
m
.
U64
);
c
heck
(
t
,
m
.
I
==
-
9
,
"i"
,
m
.
I
);
c
heck
(
t
,
m
.
U
==
10
,
"u"
,
m
.
U
);
c
heck
(
t
,
m
.
Fl
==
11.5
,
"fl"
,
m
.
Fl
);
c
heck
(
t
,
m
.
Fl32
==
12.25
,
"fl32"
,
m
.
Fl32
);
c
heck
(
t
,
m
.
Fl64
==
13.75
,
"fl64"
,
m
.
Fl64
);
c
heck
(
t
,
m
.
A
!=
nil
,
"a"
,
m
.
A
);
if
m
.
A
!=
nil
{
_C
heck
(
t
,
m
.
A
[
0
]
==
"x"
,
"a[0]"
,
m
.
A
[
0
]);
_C
heck
(
t
,
m
.
A
[
1
]
==
"y"
,
"a[1]"
,
m
.
A
[
1
]);
_C
heck
(
t
,
m
.
A
[
2
]
==
"z"
,
"a[2]"
,
m
.
A
[
2
]);
c
heck
(
t
,
m
.
A
[
0
]
==
"x"
,
"a[0]"
,
m
.
A
[
0
]);
c
heck
(
t
,
m
.
A
[
1
]
==
"y"
,
"a[1]"
,
m
.
A
[
1
]);
c
heck
(
t
,
m
.
A
[
2
]
==
"z"
,
"a[2]"
,
m
.
A
[
2
]);
}
_C
heck
(
t
,
m
.
My
!=
nil
,
"my"
,
m
.
My
);
c
heck
(
t
,
m
.
My
!=
nil
,
"my"
,
m
.
My
);
if
m
.
My
!=
nil
{
_C
heck
(
t
,
m
.
My
.
S
==
"subguy"
,
"my.s"
,
m
.
My
.
S
);
c
heck
(
t
,
m
.
My
.
S
==
"subguy"
,
"my.s"
,
m
.
My
.
S
);
}
check
(
t
,
reflect
.
DeepEqual
(
m
.
Map
,
decodedMap
),
"map"
,
m
.
Map
);
check
(
t
,
reflect
.
DeepEqual
(
m
.
MapStruct
,
decodedMapStruct
),
"mapstruct"
,
m
.
MapStruct
);
check
(
t
,
reflect
.
DeepEqual
(
m
.
MapPtrStruct
,
decodedMapPtrStruct
),
"mapptrstruct"
,
m
.
MapPtrStruct
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment