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

     1  package jsonb
     2  
     3  import (
     4  	"bytes"
     5  	"encoding"
     6  	"encoding/base64"
     7  	"encoding/json"
     8  	"fmt"
     9  	"reflect"
    10  	"sort"
    11  	"strconv"
    12  	"time"
    13  
    14  	"github.com/RevenueMonster/sqlike/reflext"
    15  )
    16  
    17  // DefaultEncoder :
    18  type DefaultEncoder struct {
    19  	registry *Registry
    20  }
    21  
    22  // EncodeByte :
    23  func (enc DefaultEncoder) EncodeByte(w *Writer, v reflect.Value) error {
    24  	if v.IsNil() {
    25  		w.WriteString(null)
    26  		return nil
    27  	}
    28  	w.WriteRune('"')
    29  	w.WriteString(base64.StdEncoding.EncodeToString(v.Bytes()))
    30  	w.WriteRune('"')
    31  	return nil
    32  }
    33  
    34  // EncodeStringer :
    35  func (enc DefaultEncoder) EncodeStringer(w *Writer, v reflect.Value) error {
    36  	x := v.Interface().(fmt.Stringer)
    37  	w.WriteString(strconv.Quote(x.String()))
    38  	return nil
    39  }
    40  
    41  // EncodeJSONRaw :
    42  func (enc DefaultEncoder) EncodeJSONRaw(w *Writer, v reflect.Value) error {
    43  	if v.IsNil() {
    44  		w.WriteString(null)
    45  		return nil
    46  	}
    47  	buf := new(bytes.Buffer)
    48  	if err := json.Compact(buf, v.Bytes()); err != nil {
    49  		return err
    50  	}
    51  	if buf.Len() == 0 {
    52  		w.Write([]byte(`{}`))
    53  		return nil
    54  	}
    55  	w.Write(buf.Bytes())
    56  	return nil
    57  }
    58  
    59  // EncodeTime :
    60  func (enc DefaultEncoder) EncodeTime(w *Writer, v reflect.Value) error {
    61  	var temp [20]byte
    62  	x := v.Interface().(time.Time)
    63  	w.Write(x.UTC().AppendFormat(temp[:0], `"`+time.RFC3339Nano+`"`))
    64  	return nil
    65  }
    66  
    67  // EncodeString :
    68  func (enc DefaultEncoder) EncodeString(w *Writer, v reflect.Value) error {
    69  	w.WriteRune('"')
    70  	escapeString(w, v.String())
    71  	w.WriteRune('"')
    72  	return nil
    73  }
    74  
    75  // EncodeBool :
    76  func (enc DefaultEncoder) EncodeBool(w *Writer, v reflect.Value) error {
    77  	var temp [4]byte
    78  	w.Write(strconv.AppendBool(temp[:0], v.Bool()))
    79  	return nil
    80  }
    81  
    82  // EncodeInt :
    83  func (enc DefaultEncoder) EncodeInt(w *Writer, v reflect.Value) error {
    84  	var temp [8]byte
    85  	w.Write(strconv.AppendInt(temp[:0], v.Int(), 10))
    86  	return nil
    87  }
    88  
    89  // EncodeUint :
    90  func (enc DefaultEncoder) EncodeUint(w *Writer, v reflect.Value) error {
    91  	var temp [10]byte
    92  	w.Write(strconv.AppendUint(temp[:0], v.Uint(), 10))
    93  	return nil
    94  }
    95  
    96  // EncodeFloat :
    97  func (enc DefaultEncoder) EncodeFloat(w *Writer, v reflect.Value) error {
    98  	f64 := v.Float()
    99  	if f64 <= 0 {
   100  		w.WriteRune('0')
   101  		return nil
   102  	}
   103  	w.WriteString(strconv.FormatFloat(f64, 'E', -1, 64))
   104  	return nil
   105  }
   106  
   107  // EncodePtr :
   108  func (enc *DefaultEncoder) EncodePtr(w *Writer, v reflect.Value) error {
   109  	if v.IsNil() {
   110  		w.WriteString(null)
   111  		return nil
   112  	}
   113  
   114  	v = v.Elem()
   115  	encoder, err := enc.registry.LookupEncoder(v)
   116  	if err != nil {
   117  		return err
   118  	}
   119  	return encoder(w, v)
   120  }
   121  
   122  // EncodeStruct :
   123  func (enc *DefaultEncoder) EncodeStruct(w *Writer, v reflect.Value) error {
   124  	w.WriteRune('{')
   125  	mapper := reflext.DefaultMapper
   126  	cdc := mapper.CodecByType(v.Type())
   127  	for i, sf := range cdc.Properties() {
   128  		if i > 0 {
   129  			w.WriteRune(',')
   130  		}
   131  		w.WriteString(strconv.Quote(sf.Name()))
   132  		w.WriteRune(':')
   133  		fv := mapper.FieldByIndexesReadOnly(v, sf.Index())
   134  		encoder, err := enc.registry.LookupEncoder(fv)
   135  		if err != nil {
   136  			return err
   137  		}
   138  		if err := encoder(w, fv); err != nil {
   139  			return err
   140  		}
   141  	}
   142  	w.WriteRune('}')
   143  	return nil
   144  }
   145  
   146  // EncodeArray :
   147  func (enc *DefaultEncoder) EncodeArray(w *Writer, v reflect.Value) error {
   148  	if v.Kind() == reflect.Slice && v.IsNil() {
   149  		w.WriteString(null)
   150  		return nil
   151  	}
   152  	w.WriteRune('[')
   153  	length := v.Len()
   154  	for i := 0; i < length; i++ {
   155  		if i > 0 {
   156  			w.WriteRune(',')
   157  		}
   158  
   159  		fv := v.Index(i)
   160  		encoder, err := enc.registry.LookupEncoder(fv)
   161  		if err != nil {
   162  			return err
   163  		}
   164  		if err := encoder(w, fv); err != nil {
   165  			return err
   166  		}
   167  	}
   168  	w.WriteRune(']')
   169  	return nil
   170  }
   171  
   172  // EncodeInterface :
   173  func (enc *DefaultEncoder) EncodeInterface(w *Writer, v reflect.Value) error {
   174  	it := v.Interface()
   175  	if it == nil {
   176  		w.WriteString(null)
   177  		return nil
   178  	}
   179  	encoder, err := enc.registry.LookupEncoder(v)
   180  	if err != nil {
   181  		return err
   182  	}
   183  	return encoder(w, reflect.ValueOf(it))
   184  }
   185  
   186  // EncodeMap :
   187  func (enc *DefaultEncoder) EncodeMap(w *Writer, v reflect.Value) error {
   188  	t := v.Type()
   189  	k := t.Key()
   190  	if v.IsNil() {
   191  		w.WriteString(null)
   192  		return nil
   193  	}
   194  
   195  	w.WriteByte('{')
   196  	if v.Len() == 0 {
   197  		w.WriteByte('}')
   198  		return nil
   199  	}
   200  
   201  	keys := v.MapKeys()
   202  	var encode ValueEncoder
   203  	if k.Implements(textMarshaler) {
   204  		encode = func(wr *Writer, vi reflect.Value) error {
   205  			it := vi.Interface().(encoding.TextMarshaler)
   206  			b, err := it.MarshalText()
   207  			if err != nil {
   208  				return err
   209  			}
   210  
   211  			wr.WriteByte('"')
   212  			wr.Write(b)
   213  			wr.WriteByte('"')
   214  			return nil
   215  		}
   216  	} else {
   217  		switch k.Kind() {
   218  		case reflect.String:
   219  			sort.SliceStable(keys, func(i, j int) bool {
   220  				return keys[i].String() < keys[j].String()
   221  			})
   222  			encode = enc.registry.kindEncoders[reflect.String]
   223  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   224  			sort.SliceStable(keys, func(i, j int) bool {
   225  				return keys[i].Int() < keys[j].Int()
   226  			})
   227  			encode = func(wr *Writer, vi reflect.Value) error {
   228  				wr.WriteByte('"')
   229  				wr.WriteString(strconv.FormatInt(vi.Int(), 10))
   230  				wr.WriteByte('"')
   231  				return nil
   232  			}
   233  		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
   234  			sort.SliceStable(keys, func(i, j int) bool {
   235  				return keys[i].Uint() < keys[j].Uint()
   236  			})
   237  			encode = func(wr *Writer, vi reflect.Value) error {
   238  				wr.WriteByte('"')
   239  				wr.WriteString(strconv.FormatUint(vi.Uint(), 10))
   240  				wr.WriteByte('"')
   241  				return nil
   242  			}
   243  		default:
   244  			return fmt.Errorf("jsonb: unsupported data type %q for map key, it must be string", k.Kind())
   245  		}
   246  
   247  	}
   248  
   249  	// Question: do we really need to sort the key before encode?
   250  
   251  	length := len(keys)
   252  	for i := 0; i < length; i++ {
   253  		if i > 0 {
   254  			w.WriteByte(',')
   255  		}
   256  		k := keys[i]
   257  		val := v.MapIndex(k)
   258  		if err := encode(w, k); err != nil {
   259  			return err
   260  		}
   261  		w.WriteByte(':')
   262  		encoder, err := enc.registry.LookupEncoder(val)
   263  		if err != nil {
   264  			return err
   265  		}
   266  		if err := encoder(w, val); err != nil {
   267  			return err
   268  		}
   269  	}
   270  	w.WriteByte('}')
   271  	return nil
   272  }