json_encoder.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. package core
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "math"
  6. "sync"
  7. "time"
  8. "unicode/utf8"
  9. )
  10. // For JSON-escaping; see jsonEncoder.safeAddString below.
  11. const _hex = "0123456789abcdef"
  12. var _ ObjectEncoder = &jsonEncoder{}
  13. var _jsonPool = sync.Pool{New: func() interface{} {
  14. return &jsonEncoder{}
  15. }}
  16. func getJSONEncoder() *jsonEncoder {
  17. return _jsonPool.Get().(*jsonEncoder)
  18. }
  19. func putJSONEncoder(enc *jsonEncoder) {
  20. if enc.reflectBuf != nil {
  21. enc.reflectBuf.Free()
  22. }
  23. enc.EncoderConfig = nil
  24. enc.buf = nil
  25. enc.spaced = false
  26. enc.openNamespaces = 0
  27. enc.reflectBuf = nil
  28. enc.reflectEnc = nil
  29. _jsonPool.Put(enc)
  30. }
  31. type jsonEncoder struct {
  32. *EncoderConfig
  33. buf *Buffer
  34. spaced bool // include spaces after colons and commas
  35. openNamespaces int
  36. // for encoding generic values by reflection
  37. reflectBuf *Buffer
  38. reflectEnc *json.Encoder
  39. }
  40. // NewJSONEncoder creates a fast, low-allocation JSON encoder. The encoder
  41. // appropriately escapes all field keys and values.
  42. //
  43. // Note that the encoder doesn't deduplicate keys, so it's possible to produce
  44. // a message like
  45. // {"foo":"bar","foo":"baz"}
  46. // This is permitted by the JSON specification, but not encouraged. Many
  47. // libraries will ignore duplicate key-value pairs (typically keeping the last
  48. // pair) when unmarshaling, but users should attempt to avoid adding duplicate
  49. // keys.
  50. func NewJSONEncoder(cfg EncoderConfig, buf *Buffer) Encoder {
  51. return newJSONEncoder(cfg, false, buf)
  52. }
  53. func newJSONEncoder(cfg EncoderConfig, spaced bool, buf *Buffer) *jsonEncoder {
  54. return &jsonEncoder{
  55. EncoderConfig: &cfg,
  56. buf: buf,
  57. spaced: spaced,
  58. }
  59. }
  60. func (enc *jsonEncoder) AddArray(key string, arr ArrayMarshaler) error {
  61. enc.addKey(key)
  62. return enc.AppendArray(arr)
  63. }
  64. func (enc *jsonEncoder) AddObject(key string, obj ObjectMarshaler) error {
  65. enc.addKey(key)
  66. return enc.AppendObject(obj)
  67. }
  68. func (enc *jsonEncoder) AddBinary(key string, val []byte) {
  69. enc.AddString(key, base64.StdEncoding.EncodeToString(val))
  70. }
  71. func (enc *jsonEncoder) AddByteString(key string, val []byte) {
  72. enc.addKey(key)
  73. enc.AppendByteString(val)
  74. }
  75. func (enc *jsonEncoder) AddBool(key string, val bool) {
  76. enc.addKey(key)
  77. enc.AppendBool(val)
  78. }
  79. func (enc *jsonEncoder) AddComplex128(key string, val complex128) {
  80. enc.addKey(key)
  81. enc.AppendComplex128(val)
  82. }
  83. func (enc *jsonEncoder) AddDuration(key string, val time.Duration) {
  84. enc.addKey(key)
  85. enc.AppendDuration(val)
  86. }
  87. func (enc *jsonEncoder) AddFloat64(key string, val float64) {
  88. enc.addKey(key)
  89. enc.AppendFloat64(val)
  90. }
  91. func (enc *jsonEncoder) AddInt64(key string, val int64) {
  92. enc.addKey(key)
  93. enc.AppendInt64(val)
  94. }
  95. func (enc *jsonEncoder) resetReflectBuf() {
  96. if enc.reflectBuf == nil {
  97. enc.reflectBuf = GetPool()
  98. enc.reflectEnc = json.NewEncoder(enc.reflectBuf)
  99. } else {
  100. enc.reflectBuf.Reset()
  101. }
  102. }
  103. func (enc *jsonEncoder) AddReflected(key string, obj interface{}) error {
  104. enc.resetReflectBuf()
  105. err := enc.reflectEnc.Encode(obj)
  106. if err != nil {
  107. return err
  108. }
  109. enc.reflectBuf.TrimNewline()
  110. enc.addKey(key)
  111. _, err = enc.buf.Write(enc.reflectBuf.Bytes())
  112. return err
  113. }
  114. func (enc *jsonEncoder) OpenNamespace(key string) {
  115. enc.addKey(key)
  116. enc.buf.AppendByte('{')
  117. enc.openNamespaces++
  118. }
  119. func (enc *jsonEncoder) AddString(key, val string) {
  120. enc.addKey(key)
  121. enc.AppendString(val)
  122. }
  123. func (enc *jsonEncoder) AddTime(key string, val time.Time) {
  124. enc.addKey(key)
  125. enc.AppendTime(val)
  126. }
  127. func (enc *jsonEncoder) AddUint64(key string, val uint64) {
  128. enc.addKey(key)
  129. enc.AppendUint64(val)
  130. }
  131. func (enc *jsonEncoder) AppendArray(arr ArrayMarshaler) error {
  132. enc.addElementSeparator()
  133. enc.buf.AppendByte('[')
  134. err := arr.MarshalLogArray(enc)
  135. enc.buf.AppendByte(']')
  136. return err
  137. }
  138. func (enc *jsonEncoder) AppendObject(obj ObjectMarshaler) error {
  139. enc.addElementSeparator()
  140. enc.buf.AppendByte('{')
  141. err := obj.MarshalLogObject(enc)
  142. enc.buf.AppendByte('}')
  143. return err
  144. }
  145. func (enc *jsonEncoder) AppendBool(val bool) {
  146. enc.addElementSeparator()
  147. enc.buf.AppendBool(val)
  148. }
  149. func (enc *jsonEncoder) AppendByteString(val []byte) {
  150. enc.addElementSeparator()
  151. enc.buf.AppendByte('"')
  152. enc.safeAddByteString(val)
  153. enc.buf.AppendByte('"')
  154. }
  155. func (enc *jsonEncoder) AppendComplex128(val complex128) {
  156. enc.addElementSeparator()
  157. // Cast to a platform-independent, fixed-size type.
  158. r, i := float64(real(val)), float64(imag(val))
  159. enc.buf.AppendByte('"')
  160. // Because we're always in a quoted string, we can use strconv without
  161. // special-casing NaN and +/-Inf.
  162. enc.buf.AppendFloat(r, 64)
  163. enc.buf.AppendByte('+')
  164. enc.buf.AppendFloat(i, 64)
  165. enc.buf.AppendByte('i')
  166. enc.buf.AppendByte('"')
  167. }
  168. func (enc *jsonEncoder) AppendDuration(val time.Duration) {
  169. cur := enc.buf.Len()
  170. enc.EncodeDuration(val, enc)
  171. if cur == enc.buf.Len() {
  172. // User-supplied EncodeDuration is a no-op. Fall back to nanoseconds to keep
  173. // JSON valid.
  174. enc.AppendInt64(int64(val))
  175. }
  176. }
  177. func (enc *jsonEncoder) AppendInt64(val int64) {
  178. enc.addElementSeparator()
  179. enc.buf.AppendInt(val)
  180. }
  181. func (enc *jsonEncoder) AppendReflected(val interface{}) error {
  182. enc.resetReflectBuf()
  183. err := enc.reflectEnc.Encode(val)
  184. if err != nil {
  185. return err
  186. }
  187. enc.reflectBuf.TrimNewline()
  188. enc.addElementSeparator()
  189. _, err = enc.buf.Write(enc.reflectBuf.Bytes())
  190. return err
  191. }
  192. func (enc *jsonEncoder) AppendString(val string) {
  193. enc.addElementSeparator()
  194. enc.buf.AppendByte('"')
  195. enc.safeAddString(val)
  196. enc.buf.AppendByte('"')
  197. }
  198. func (enc *jsonEncoder) AppendTime(val time.Time) {
  199. cur := enc.buf.Len()
  200. enc.EncodeTime(val, enc)
  201. if cur == enc.buf.Len() {
  202. // User-supplied EncodeTime is a no-op. Fall back to nanos since epoch to keep
  203. // output JSON valid.
  204. enc.AppendInt64(val.UnixNano())
  205. }
  206. }
  207. func (enc *jsonEncoder) AppendUint64(val uint64) {
  208. enc.addElementSeparator()
  209. enc.buf.AppendUint(val)
  210. }
  211. func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) }
  212. func (enc *jsonEncoder) AddFloat32(k string, v float32) { enc.AddFloat64(k, float64(v)) }
  213. func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) }
  214. func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) }
  215. func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) }
  216. func (enc *jsonEncoder) AddInt8(k string, v int8) { enc.AddInt64(k, int64(v)) }
  217. func (enc *jsonEncoder) AddUint(k string, v uint) { enc.AddUint64(k, uint64(v)) }
  218. func (enc *jsonEncoder) AddUint32(k string, v uint32) { enc.AddUint64(k, uint64(v)) }
  219. func (enc *jsonEncoder) AddUint16(k string, v uint16) { enc.AddUint64(k, uint64(v)) }
  220. func (enc *jsonEncoder) AddUint8(k string, v uint8) { enc.AddUint64(k, uint64(v)) }
  221. func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) }
  222. func (enc *jsonEncoder) AppendComplex64(v complex64) { enc.AppendComplex128(complex128(v)) }
  223. func (enc *jsonEncoder) AppendFloat64(v float64) { enc.appendFloat(v, 64) }
  224. func (enc *jsonEncoder) AppendFloat32(v float32) { enc.appendFloat(float64(v), 32) }
  225. func (enc *jsonEncoder) AppendInt(v int) { enc.AppendInt64(int64(v)) }
  226. func (enc *jsonEncoder) AppendInt32(v int32) { enc.AppendInt64(int64(v)) }
  227. func (enc *jsonEncoder) AppendInt16(v int16) { enc.AppendInt64(int64(v)) }
  228. func (enc *jsonEncoder) AppendInt8(v int8) { enc.AppendInt64(int64(v)) }
  229. func (enc *jsonEncoder) AppendUint(v uint) { enc.AppendUint64(uint64(v)) }
  230. func (enc *jsonEncoder) AppendUint32(v uint32) { enc.AppendUint64(uint64(v)) }
  231. func (enc *jsonEncoder) AppendUint16(v uint16) { enc.AppendUint64(uint64(v)) }
  232. func (enc *jsonEncoder) AppendUint8(v uint8) { enc.AppendUint64(uint64(v)) }
  233. func (enc *jsonEncoder) AppendUintptr(v uintptr) { enc.AppendUint64(uint64(v)) }
  234. func (enc *jsonEncoder) Clone() Encoder {
  235. clone := enc.clone()
  236. return clone
  237. }
  238. func (enc *jsonEncoder) clone() *jsonEncoder {
  239. clone := getJSONEncoder()
  240. clone.EncoderConfig = enc.EncoderConfig
  241. clone.spaced = enc.spaced
  242. clone.openNamespaces = enc.openNamespaces
  243. clone.buf = GetPool()
  244. return clone
  245. }
  246. func (enc *jsonEncoder) Encode(buf *Buffer, fields ...Field) error {
  247. final := enc.clone()
  248. final.buf = buf
  249. final.buf.AppendByte('{')
  250. if enc.buf.Len() > 0 {
  251. final.addElementSeparator()
  252. final.buf.Write(enc.buf.Bytes())
  253. }
  254. for i := range fields {
  255. fields[i].AddTo(final)
  256. }
  257. final.closeOpenNamespaces()
  258. final.buf.AppendString("}\n")
  259. putJSONEncoder(final)
  260. return nil
  261. }
  262. func (enc *jsonEncoder) closeOpenNamespaces() {
  263. for i := 0; i < enc.openNamespaces; i++ {
  264. enc.buf.AppendByte('}')
  265. }
  266. }
  267. func (enc *jsonEncoder) addKey(key string) {
  268. enc.addElementSeparator()
  269. enc.buf.AppendByte('"')
  270. enc.safeAddString(key)
  271. enc.buf.AppendByte('"')
  272. enc.buf.AppendByte(':')
  273. if enc.spaced {
  274. enc.buf.AppendByte(' ')
  275. }
  276. }
  277. func (enc *jsonEncoder) addElementSeparator() {
  278. last := enc.buf.Len() - 1
  279. if last < 0 {
  280. return
  281. }
  282. switch enc.buf.Bytes()[last] {
  283. case '{', '[', ':', ',', ' ':
  284. return
  285. default:
  286. enc.buf.AppendByte(',')
  287. if enc.spaced {
  288. enc.buf.AppendByte(' ')
  289. }
  290. }
  291. }
  292. func (enc *jsonEncoder) appendFloat(val float64, bitSize int) {
  293. enc.addElementSeparator()
  294. switch {
  295. case math.IsNaN(val):
  296. enc.buf.AppendString(`"NaN"`)
  297. case math.IsInf(val, 1):
  298. enc.buf.AppendString(`"+Inf"`)
  299. case math.IsInf(val, -1):
  300. enc.buf.AppendString(`"-Inf"`)
  301. default:
  302. enc.buf.AppendFloat(val, bitSize)
  303. }
  304. }
  305. // safeAddString JSON-escapes a string and appends it to the internal buffer.
  306. // Unlike the standard library's encoder, it doesn't attempt to protect the
  307. // user from browser vulnerabilities or JSONP-related problems.
  308. func (enc *jsonEncoder) safeAddString(s string) {
  309. for i := 0; i < len(s); {
  310. if enc.tryAddRuneSelf(s[i]) {
  311. i++
  312. continue
  313. }
  314. r, size := utf8.DecodeRuneInString(s[i:])
  315. if enc.tryAddRuneError(r, size) {
  316. i++
  317. continue
  318. }
  319. enc.buf.AppendString(s[i : i+size])
  320. i += size
  321. }
  322. }
  323. // safeAddByteString is no-alloc equivalent of safeAddString(string(s)) for s []byte.
  324. func (enc *jsonEncoder) safeAddByteString(s []byte) {
  325. for i := 0; i < len(s); {
  326. if enc.tryAddRuneSelf(s[i]) {
  327. i++
  328. continue
  329. }
  330. r, size := utf8.DecodeRune(s[i:])
  331. if enc.tryAddRuneError(r, size) {
  332. i++
  333. continue
  334. }
  335. enc.buf.Write(s[i : i+size])
  336. i += size
  337. }
  338. }
  339. // tryAddRuneSelf appends b if it is valid UTF-8 character represented in a single byte.
  340. func (enc *jsonEncoder) tryAddRuneSelf(b byte) bool {
  341. if b >= utf8.RuneSelf {
  342. return false
  343. }
  344. if 0x20 <= b && b != '\\' && b != '"' {
  345. enc.buf.AppendByte(b)
  346. return true
  347. }
  348. switch b {
  349. case '\\', '"':
  350. enc.buf.AppendByte('\\')
  351. enc.buf.AppendByte(b)
  352. case '\n':
  353. enc.buf.AppendByte('\\')
  354. enc.buf.AppendByte('n')
  355. case '\r':
  356. enc.buf.AppendByte('\\')
  357. enc.buf.AppendByte('r')
  358. case '\t':
  359. enc.buf.AppendByte('\\')
  360. enc.buf.AppendByte('t')
  361. default:
  362. // Encode bytes < 0x20, except for the escape sequences above.
  363. enc.buf.AppendString(`\u00`)
  364. enc.buf.AppendByte(_hex[b>>4])
  365. enc.buf.AppendByte(_hex[b&0xF])
  366. }
  367. return true
  368. }
  369. func (enc *jsonEncoder) tryAddRuneError(r rune, size int) bool {
  370. if r == utf8.RuneError && size == 1 {
  371. enc.buf.AppendString(`\ufffd`)
  372. return true
  373. }
  374. return false
  375. }