mirror of
https://github.com/golang/go
synced 2024-10-05 12:31:23 -06:00
215 lines
4.5 KiB
Go
215 lines
4.5 KiB
Go
|
// 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.
|
||
|
|
||
|
// Marshalling and unmarshalling of
|
||
|
// JSON data into Go structs using reflection.
|
||
|
|
||
|
package json
|
||
|
|
||
|
import (
|
||
|
"json";
|
||
|
"reflect";
|
||
|
)
|
||
|
|
||
|
type StructBuilder struct {
|
||
|
val reflect.Value
|
||
|
}
|
||
|
|
||
|
var nobuilder *StructBuilder
|
||
|
|
||
|
func SetFloat(v reflect.Value, f float64) {
|
||
|
switch v.Kind() {
|
||
|
case reflect.FloatKind:
|
||
|
v.(reflect.FloatValue).Set(float(f));
|
||
|
case reflect.Float32Kind:
|
||
|
v.(reflect.Float32Value).Set(float32(f));
|
||
|
case reflect.Float64Kind:
|
||
|
v.(reflect.Float64Value).Set(float64(f));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func SetInt(v reflect.Value, i int64) {
|
||
|
switch v.Kind() {
|
||
|
case reflect.IntKind:
|
||
|
v.(reflect.IntValue).Set(int(i));
|
||
|
case reflect.Int8Kind:
|
||
|
v.(reflect.Int8Value).Set(int8(i));
|
||
|
case reflect.Int16Kind:
|
||
|
v.(reflect.Int16Value).Set(int16(i));
|
||
|
case reflect.Int32Kind:
|
||
|
v.(reflect.Int32Value).Set(int32(i));
|
||
|
case reflect.Int64Kind:
|
||
|
v.(reflect.Int64Value).Set(int64(i));
|
||
|
case reflect.UintKind:
|
||
|
v.(reflect.UintValue).Set(uint(i));
|
||
|
case reflect.Uint8Kind:
|
||
|
v.(reflect.Uint8Value).Set(uint8(i));
|
||
|
case reflect.Uint16Kind:
|
||
|
v.(reflect.Uint16Value).Set(uint16(i));
|
||
|
case reflect.Uint32Kind:
|
||
|
v.(reflect.Uint32Value).Set(uint32(i));
|
||
|
case reflect.Uint64Kind:
|
||
|
v.(reflect.Uint64Value).Set(uint64(i));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) Int64(i int64) {
|
||
|
if b == nil {
|
||
|
return
|
||
|
}
|
||
|
v := b.val;
|
||
|
switch v.Kind() {
|
||
|
case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind:
|
||
|
SetFloat(v, float64(i));
|
||
|
default:
|
||
|
SetInt(v, i);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) Uint64(i uint64) {
|
||
|
if b == nil {
|
||
|
return
|
||
|
}
|
||
|
v := b.val;
|
||
|
switch v.Kind() {
|
||
|
case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind:
|
||
|
SetFloat(v, float64(i));
|
||
|
default:
|
||
|
SetInt(v, int64(i));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) Float64(f float64) {
|
||
|
if b == nil {
|
||
|
return
|
||
|
}
|
||
|
v := b.val;
|
||
|
switch v.Kind() {
|
||
|
case reflect.FloatKind, reflect.Float32Kind, reflect.Float64Kind:
|
||
|
SetFloat(v, f);
|
||
|
default:
|
||
|
SetInt(v, int64(f));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) Null() {
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) String(s string) {
|
||
|
if b == nil {
|
||
|
return
|
||
|
}
|
||
|
if v := b.val; v.Kind() == reflect.StringKind {
|
||
|
v.(reflect.StringValue).Set(s);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) Bool(tf bool) {
|
||
|
if b == nil {
|
||
|
return
|
||
|
}
|
||
|
if v := b.val; v.Kind() == reflect.BoolKind {
|
||
|
v.(reflect.BoolValue).Set(tf);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) Array() {
|
||
|
if b == nil {
|
||
|
return
|
||
|
}
|
||
|
if v := b.val; v.Kind() == reflect.PtrKind {
|
||
|
pv := v.(reflect.PtrValue);
|
||
|
psubtype := pv.Type().(reflect.PtrType).Sub();
|
||
|
if pv.Get() == nil && psubtype.Kind() == reflect.ArrayKind {
|
||
|
av := reflect.NewOpenArrayValue(psubtype, 0, 8);
|
||
|
pv.SetSub(av);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) Elem(i int) Builder {
|
||
|
if b == nil || i < 0 {
|
||
|
return nobuilder
|
||
|
}
|
||
|
v := b.val;
|
||
|
if v.Kind() == reflect.PtrKind {
|
||
|
// If we have a pointer to an array, allocate or grow
|
||
|
// the array as necessary. Then set v to the array itself.
|
||
|
pv := v.(reflect.PtrValue);
|
||
|
psub := pv.Sub();
|
||
|
if psub.Kind() == reflect.ArrayKind {
|
||
|
av := psub.(reflect.ArrayValue);
|
||
|
if i > av.Cap() {
|
||
|
n := av.Cap();
|
||
|
if n < 8 {
|
||
|
n = 8
|
||
|
}
|
||
|
for n <= i {
|
||
|
n *= 2
|
||
|
}
|
||
|
av1 := reflect.NewOpenArrayValue(av.Type(), av.Len(), n);
|
||
|
reflect.CopyArray(av1, av, av.Len());
|
||
|
pv.SetSub(av1);
|
||
|
av = av1;
|
||
|
}
|
||
|
}
|
||
|
v = psub;
|
||
|
}
|
||
|
if v.Kind() == reflect.ArrayKind {
|
||
|
// Array was grown above, or is fixed size.
|
||
|
av := v.(reflect.ArrayValue);
|
||
|
if av.Len() <= i && i < av.Cap() {
|
||
|
av.SetLen(i+1);
|
||
|
}
|
||
|
if i < av.Len() {
|
||
|
return &StructBuilder{ av.Elem(i) }
|
||
|
}
|
||
|
}
|
||
|
return nobuilder
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) Map() {
|
||
|
if b == nil {
|
||
|
return
|
||
|
}
|
||
|
if v := b.val; v.Kind() == reflect.PtrKind {
|
||
|
pv := v.(reflect.PtrValue);
|
||
|
if pv.Get() == nil {
|
||
|
pv.SetSub(reflect.NewInitValue(pv.Type().(reflect.PtrType).Sub()))
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (b *StructBuilder) Key(k string) Builder {
|
||
|
if b == nil {
|
||
|
return nobuilder
|
||
|
}
|
||
|
v := b.val;
|
||
|
if v.Kind() == reflect.PtrKind {
|
||
|
v = v.(reflect.PtrValue).Sub();
|
||
|
}
|
||
|
if v.Kind() == reflect.StructKind {
|
||
|
sv := v.(reflect.StructValue);
|
||
|
t := v.Type().(reflect.StructType);
|
||
|
for i := 0; i < t.Len(); i++ {
|
||
|
name, typ, tag, off := t.Field(i);
|
||
|
if k == name {
|
||
|
return &StructBuilder{ sv.Field(i) }
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return nobuilder
|
||
|
}
|
||
|
|
||
|
export func Unmarshal(s string, val interface{}) (ok bool, errtok string) {
|
||
|
var errindx int;
|
||
|
var val1 interface{};
|
||
|
b := &StructBuilder{ reflect.NewValue(val) };
|
||
|
ok, errindx, errtok = Parse(s, b);
|
||
|
if !ok {
|
||
|
return false, errtok
|
||
|
}
|
||
|
return true, ""
|
||
|
}
|