github.com/RevenueMonster/sqlike@v1.0.6/jsonb/unmarshal.go (about)

     1  package jsonb
     2  
     3  import (
     4  	"bytes"
     5  	"encoding"
     6  	"encoding/json"
     7  	"fmt"
     8  	"reflect"
     9  
    10  	"errors"
    11  
    12  	"github.com/RevenueMonster/sqlike/reflext"
    13  )
    14  
    15  // Unmarshaler :
    16  type Unmarshaler interface {
    17  	UnmarshalJSONB([]byte) error
    18  }
    19  
    20  // Unmarshal :
    21  func Unmarshal(data []byte, dst interface{}) error {
    22  	v := reflext.ValueOf(dst)
    23  	if !v.IsValid() {
    24  		return errors.New("invalid value for Unmarshal")
    25  	}
    26  
    27  	t := v.Type()
    28  	if !reflext.IsKind(t, reflect.Ptr) {
    29  		return errors.New("unaddressable destination")
    30  	}
    31  
    32  	v = v.Elem()
    33  	if !v.CanSet() {
    34  		return errors.New("unaddressable destination")
    35  	}
    36  
    37  	t = t.Elem()
    38  	decoder, err := registry.LookupDecoder(t)
    39  	if err != nil {
    40  		return err
    41  	}
    42  
    43  	r := NewReader(data)
    44  	vv := reflext.Zero(t)
    45  	if err := decoder(r, vv); err != nil {
    46  		return err
    47  	}
    48  
    49  	c := r.nextToken()
    50  	if c != 0 {
    51  		return ErrInvalidJSON{
    52  			callback: "Unmarshal",
    53  			message:  fmt.Sprintf("invalid json string, extra char %q found", c),
    54  		}
    55  	}
    56  	v.Set(vv)
    57  	return nil
    58  }
    59  
    60  // UnmarshalValue :
    61  func UnmarshalValue(data []byte, v reflect.Value) error {
    62  	if data == nil {
    63  		v.Set(reflect.Zero(v.Type()))
    64  		return nil
    65  	}
    66  
    67  	t := v.Type()
    68  	decoder, err := registry.LookupDecoder(reflext.Deref(t))
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	r := NewReader(data)
    74  	vv := reflext.Zero(t)
    75  
    76  	vv = reflext.Indirect(vv)
    77  	if err := decoder(r, vv); err != nil {
    78  		return err
    79  	}
    80  
    81  	c := r.nextToken()
    82  	if c != 0 {
    83  		return ErrInvalidJSON{
    84  			callback: "Unmarshal",
    85  		}
    86  	}
    87  	reflext.Indirect(v).Set(vv)
    88  	return nil
    89  }
    90  
    91  // unmarshalerDecoder
    92  func unmarshalerDecoder() ValueDecoder {
    93  	return func(r *Reader, v reflect.Value) error {
    94  		if r.IsNull() {
    95  			v.Set(reflect.New(v.Type()).Elem())
    96  			return r.skipNull()
    97  		}
    98  
    99  		r.pos = r.len
   100  		if v.Kind() != reflect.Ptr {
   101  			return v.Addr().Interface().(Unmarshaler).UnmarshalJSONB(r.Bytes())
   102  		}
   103  		return reflext.Init(v).Interface().(Unmarshaler).UnmarshalJSONB(r.Bytes())
   104  	}
   105  }
   106  
   107  // jsonUnmarshalerDecoder
   108  func jsonUnmarshalerDecoder() ValueDecoder {
   109  	return func(r *Reader, v reflect.Value) error {
   110  		if r.IsNull() {
   111  			v.Set(reflect.New(v.Type()).Elem())
   112  			return r.skipNull()
   113  		}
   114  
   115  		r.pos = r.len
   116  		if v.Kind() != reflect.Ptr {
   117  			return v.Addr().Interface().(json.Unmarshaler).UnmarshalJSON(r.Bytes())
   118  		}
   119  		return reflext.Init(v).Interface().(json.Unmarshaler).UnmarshalJSON(r.Bytes())
   120  	}
   121  }
   122  
   123  // textUnmarshalerDecoder
   124  func textUnmarshalerDecoder() ValueDecoder {
   125  	return func(r *Reader, v reflect.Value) error {
   126  		if r.IsNull() {
   127  			v.Set(reflect.New(v.Type()).Elem())
   128  			return r.skipNull()
   129  		}
   130  
   131  		r.pos = r.len
   132  		b := r.Bytes()
   133  		b = bytes.Trim(b, `"`)
   134  		if v.Kind() != reflect.Ptr {
   135  			return v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
   136  		}
   137  		return reflext.Init(v).Interface().(encoding.TextUnmarshaler).UnmarshalText(b)
   138  	}
   139  }