...

Source file src/github.com/aws/smithy-go/encoding/json/value.go

Documentation: github.com/aws/smithy-go/encoding/json

     1  package json
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"math/big"
     7  	"strconv"
     8  
     9  	"github.com/aws/smithy-go/encoding"
    10  )
    11  
    12  // Value represents a JSON Value type
    13  // JSON Value types: Object, Array, String, Number, Boolean, and Null
    14  type Value struct {
    15  	w       *bytes.Buffer
    16  	scratch *[]byte
    17  }
    18  
    19  // newValue returns a new Value encoder
    20  func newValue(w *bytes.Buffer, scratch *[]byte) Value {
    21  	return Value{w: w, scratch: scratch}
    22  }
    23  
    24  // String encodes v as a JSON string
    25  func (jv Value) String(v string) {
    26  	escapeStringBytes(jv.w, []byte(v))
    27  }
    28  
    29  // Byte encodes v as a JSON number
    30  func (jv Value) Byte(v int8) {
    31  	jv.Long(int64(v))
    32  }
    33  
    34  // Short encodes v as a JSON number
    35  func (jv Value) Short(v int16) {
    36  	jv.Long(int64(v))
    37  }
    38  
    39  // Integer encodes v as a JSON number
    40  func (jv Value) Integer(v int32) {
    41  	jv.Long(int64(v))
    42  }
    43  
    44  // Long encodes v as a JSON number
    45  func (jv Value) Long(v int64) {
    46  	*jv.scratch = strconv.AppendInt((*jv.scratch)[:0], v, 10)
    47  	jv.w.Write(*jv.scratch)
    48  }
    49  
    50  // ULong encodes v as a JSON number
    51  func (jv Value) ULong(v uint64) {
    52  	*jv.scratch = strconv.AppendUint((*jv.scratch)[:0], v, 10)
    53  	jv.w.Write(*jv.scratch)
    54  }
    55  
    56  // Float encodes v as a JSON number
    57  func (jv Value) Float(v float32) {
    58  	jv.float(float64(v), 32)
    59  }
    60  
    61  // Double encodes v as a JSON number
    62  func (jv Value) Double(v float64) {
    63  	jv.float(v, 64)
    64  }
    65  
    66  func (jv Value) float(v float64, bits int) {
    67  	*jv.scratch = encoding.EncodeFloat((*jv.scratch)[:0], v, bits)
    68  	jv.w.Write(*jv.scratch)
    69  }
    70  
    71  // Boolean encodes v as a JSON boolean
    72  func (jv Value) Boolean(v bool) {
    73  	*jv.scratch = strconv.AppendBool((*jv.scratch)[:0], v)
    74  	jv.w.Write(*jv.scratch)
    75  }
    76  
    77  // Base64EncodeBytes writes v as a base64 value in JSON string
    78  func (jv Value) Base64EncodeBytes(v []byte) {
    79  	encodeByteSlice(jv.w, (*jv.scratch)[:0], v)
    80  }
    81  
    82  // Write writes v directly to the JSON document
    83  func (jv Value) Write(v []byte) {
    84  	jv.w.Write(v)
    85  }
    86  
    87  // Array returns a new Array encoder
    88  func (jv Value) Array() *Array {
    89  	return newArray(jv.w, jv.scratch)
    90  }
    91  
    92  // Object returns a new Object encoder
    93  func (jv Value) Object() *Object {
    94  	return newObject(jv.w, jv.scratch)
    95  }
    96  
    97  // Null encodes a null JSON value
    98  func (jv Value) Null() {
    99  	jv.w.WriteString(null)
   100  }
   101  
   102  // BigInteger encodes v as JSON value
   103  func (jv Value) BigInteger(v *big.Int) {
   104  	jv.w.Write([]byte(v.Text(10)))
   105  }
   106  
   107  // BigDecimal encodes v as JSON value
   108  func (jv Value) BigDecimal(v *big.Float) {
   109  	if i, accuracy := v.Int64(); accuracy == big.Exact {
   110  		jv.Long(i)
   111  		return
   112  	}
   113  	// TODO: Should this try to match ES6 ToString similar to stdlib JSON?
   114  	jv.w.Write([]byte(v.Text('e', -1)))
   115  }
   116  
   117  // Based on encoding/json encodeByteSlice from the Go Standard Library
   118  // https://golang.org/src/encoding/json/encode.go
   119  func encodeByteSlice(w *bytes.Buffer, scratch []byte, v []byte) {
   120  	if v == nil {
   121  		w.WriteString(null)
   122  		return
   123  	}
   124  
   125  	w.WriteRune(quote)
   126  
   127  	encodedLen := base64.StdEncoding.EncodedLen(len(v))
   128  	if encodedLen <= len(scratch) {
   129  		// If the encoded bytes fit in e.scratch, avoid an extra
   130  		// allocation and use the cheaper Encoding.Encode.
   131  		dst := scratch[:encodedLen]
   132  		base64.StdEncoding.Encode(dst, v)
   133  		w.Write(dst)
   134  	} else if encodedLen <= 1024 {
   135  		// The encoded bytes are short enough to allocate for, and
   136  		// Encoding.Encode is still cheaper.
   137  		dst := make([]byte, encodedLen)
   138  		base64.StdEncoding.Encode(dst, v)
   139  		w.Write(dst)
   140  	} else {
   141  		// The encoded bytes are too long to cheaply allocate, and
   142  		// Encoding.Encode is no longer noticeably cheaper.
   143  		enc := base64.NewEncoder(base64.StdEncoding, w)
   144  		enc.Write(v)
   145  		enc.Close()
   146  	}
   147  
   148  	w.WriteRune(quote)
   149  }
   150  

View as plain text