github.com/go-spring/spring-base@v1.1.3/log/field_encoder.go (about) 1 /* 2 * Copyright 2012-2019 the original author or authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package log 18 19 import ( 20 "bytes" 21 "encoding/json" 22 "strconv" 23 "unicode/utf8" 24 ) 25 26 // An Encoder is used to serialize strongly-typed Field. 27 type Encoder interface { 28 AppendEncoderBegin() error 29 AppendEncoderEnd() error 30 AppendObjectBegin() error 31 AppendObjectEnd() error 32 AppendArrayBegin() error 33 AppendArrayEnd() error 34 AppendKey(key string) error 35 AppendBool(v bool) error 36 AppendInt64(v int64) error 37 AppendUint64(v uint64) error 38 AppendFloat64(v float64) error 39 AppendString(v string) error 40 AppendReflect(v interface{}) error 41 } 42 43 var ( 44 _ Encoder = (*JSONEncoder)(nil) 45 _ Encoder = (*FlatEncoder)(nil) 46 ) 47 48 type jsonToken int 49 50 const ( 51 jsonTokenUnknown jsonToken = iota 52 jsonTokenObjectBegin 53 jsonTokenObjectEnd 54 jsonTokenArrayBegin 55 jsonTokenArrayEnd 56 jsonTokenKey 57 jsonTokenValue 58 ) 59 60 // JSONEncoder encodes Fields in json format. 61 type JSONEncoder struct { 62 buf *bytes.Buffer 63 last jsonToken 64 } 65 66 // NewJSONEncoder returns a new *JSONEncoder. 67 func NewJSONEncoder(buf *bytes.Buffer) *JSONEncoder { 68 return &JSONEncoder{ 69 buf: buf, 70 last: jsonTokenUnknown, 71 } 72 } 73 74 // Reset resets the *JSONEncoder. 75 func (enc *JSONEncoder) Reset() { 76 enc.last = jsonTokenUnknown 77 } 78 79 // AppendEncoderBegin appends an encoder begin character. 80 func (enc *JSONEncoder) AppendEncoderBegin() error { 81 enc.last = jsonTokenObjectBegin 82 enc.buf.WriteByte('{') 83 return nil 84 } 85 86 // AppendEncoderEnd appends an encoder end character. 87 func (enc *JSONEncoder) AppendEncoderEnd() error { 88 enc.last = jsonTokenObjectEnd 89 enc.buf.WriteByte('}') 90 return nil 91 } 92 93 // AppendObjectBegin appends a object begin character. 94 func (enc *JSONEncoder) AppendObjectBegin() error { 95 enc.last = jsonTokenObjectBegin 96 enc.buf.WriteByte('{') 97 return nil 98 } 99 100 // AppendObjectEnd appends an object end character. 101 func (enc *JSONEncoder) AppendObjectEnd() error { 102 enc.last = jsonTokenObjectEnd 103 enc.buf.WriteByte('}') 104 return nil 105 } 106 107 // AppendArrayBegin appends an array begin character. 108 func (enc *JSONEncoder) AppendArrayBegin() error { 109 enc.last = jsonTokenArrayBegin 110 enc.buf.WriteByte('[') 111 return nil 112 } 113 114 // AppendArrayEnd appends an array end character. 115 func (enc *JSONEncoder) AppendArrayEnd() error { 116 enc.last = jsonTokenArrayEnd 117 enc.buf.WriteByte(']') 118 return nil 119 } 120 121 func (enc *JSONEncoder) appendSeparator(curr jsonToken) { 122 switch curr { 123 case jsonTokenKey: 124 if enc.last == jsonTokenObjectEnd || enc.last == jsonTokenArrayEnd || enc.last == jsonTokenValue { 125 enc.buf.WriteByte(',') 126 } 127 case jsonTokenValue: 128 if enc.last == jsonTokenValue { 129 enc.buf.WriteByte(',') 130 } 131 } 132 } 133 134 // AppendKey appends a key. 135 func (enc *JSONEncoder) AppendKey(key string) error { 136 enc.appendSeparator(jsonTokenKey) 137 enc.last = jsonTokenKey 138 enc.buf.WriteByte('"') 139 enc.safeAddString(key) 140 enc.buf.WriteByte('"') 141 enc.buf.WriteByte(':') 142 return nil 143 } 144 145 // AppendBool appends a bool. 146 func (enc *JSONEncoder) AppendBool(v bool) error { 147 enc.appendSeparator(jsonTokenValue) 148 enc.last = jsonTokenValue 149 enc.buf.WriteString(strconv.FormatBool(v)) 150 return nil 151 } 152 153 // AppendInt64 appends an int64. 154 func (enc *JSONEncoder) AppendInt64(v int64) error { 155 enc.appendSeparator(jsonTokenValue) 156 enc.last = jsonTokenValue 157 enc.buf.WriteString(strconv.FormatInt(v, 10)) 158 return nil 159 } 160 161 // AppendUint64 appends a uint64. 162 func (enc *JSONEncoder) AppendUint64(u uint64) error { 163 enc.appendSeparator(jsonTokenValue) 164 enc.last = jsonTokenValue 165 enc.buf.WriteString(strconv.FormatUint(u, 10)) 166 return nil 167 } 168 169 // AppendFloat64 appends a float64. 170 func (enc *JSONEncoder) AppendFloat64(v float64) error { 171 enc.appendSeparator(jsonTokenValue) 172 enc.last = jsonTokenValue 173 enc.buf.WriteString(strconv.FormatFloat(v, 'f', -1, 64)) 174 return nil 175 } 176 177 // AppendString appends a string. 178 func (enc *JSONEncoder) AppendString(v string) error { 179 enc.appendSeparator(jsonTokenValue) 180 enc.last = jsonTokenValue 181 enc.buf.WriteByte('"') 182 enc.safeAddString(v) 183 enc.buf.WriteByte('"') 184 return nil 185 } 186 187 // AppendReflect appends an interface{}. 188 func (enc *JSONEncoder) AppendReflect(v interface{}) error { 189 b, err := json.Marshal(v) 190 if err != nil { 191 return err 192 } 193 enc.appendSeparator(jsonTokenValue) 194 enc.last = jsonTokenValue 195 enc.buf.Write(b) 196 return nil 197 } 198 199 // safeAddString JSON-escapes a string and appends it to the buf. 200 func (enc *JSONEncoder) safeAddString(s string) { 201 for i := 0; i < len(s); { 202 if enc.tryAddRuneSelf(s[i]) { 203 i++ 204 continue 205 } 206 r, size := utf8.DecodeRuneInString(s[i:]) 207 if enc.tryAddRuneError(r, size) { 208 i++ 209 continue 210 } 211 enc.buf.WriteString(s[i : i+size]) 212 i += size 213 } 214 } 215 216 // tryAddRuneSelf appends b if it's valid UTF-8 character represented in a single byte. 217 func (enc *JSONEncoder) tryAddRuneSelf(b byte) bool { 218 const _hex = "0123456789abcdef" 219 if b >= utf8.RuneSelf { 220 return false 221 } 222 if 0x20 <= b && b != '\\' && b != '"' { 223 enc.buf.WriteByte(b) 224 return true 225 } 226 switch b { 227 case '\\', '"': 228 enc.buf.WriteByte('\\') 229 enc.buf.WriteByte(b) 230 case '\n': 231 enc.buf.WriteByte('\\') 232 enc.buf.WriteByte('n') 233 case '\r': 234 enc.buf.WriteByte('\\') 235 enc.buf.WriteByte('r') 236 case '\t': 237 enc.buf.WriteByte('\\') 238 enc.buf.WriteByte('t') 239 default: 240 // Encode bytes < 0x20, except for the escape sequences above. 241 enc.buf.WriteString(`\u00`) 242 enc.buf.WriteByte(_hex[b>>4]) 243 enc.buf.WriteByte(_hex[b&0xF]) 244 } 245 return true 246 } 247 248 func (enc *JSONEncoder) tryAddRuneError(r rune, size int) bool { 249 if r == utf8.RuneError && size == 1 { 250 enc.buf.WriteString(`\ufffd`) 251 return true 252 } 253 return false 254 } 255 256 // FlatEncoder encodes Fields in flat format. 257 type FlatEncoder struct { 258 buf *bytes.Buffer 259 separator string 260 jsonEncoder *JSONEncoder 261 jsonDepth int8 262 init bool 263 } 264 265 // NewFlatEncoder return a new *FlatEncoder with separator. 266 func NewFlatEncoder(buf *bytes.Buffer, separator string) *FlatEncoder { 267 return &FlatEncoder{ 268 buf: buf, 269 separator: separator, 270 jsonEncoder: &JSONEncoder{buf: buf}, 271 } 272 } 273 274 // AppendEncoderBegin appends an encoder begin character. 275 func (enc *FlatEncoder) AppendEncoderBegin() error { 276 return nil 277 } 278 279 // AppendEncoderEnd appends an encoder end character. 280 func (enc *FlatEncoder) AppendEncoderEnd() error { 281 return nil 282 } 283 284 // AppendObjectBegin appends a object begin character. 285 func (enc *FlatEncoder) AppendObjectBegin() error { 286 enc.jsonDepth++ 287 return enc.jsonEncoder.AppendObjectBegin() 288 } 289 290 // AppendObjectEnd appends an object end character. 291 func (enc *FlatEncoder) AppendObjectEnd() error { 292 enc.jsonDepth-- 293 err := enc.jsonEncoder.AppendObjectEnd() 294 if enc.jsonDepth == 0 { 295 enc.jsonEncoder.Reset() 296 } 297 return err 298 } 299 300 // AppendArrayBegin appends an array begin character. 301 func (enc *FlatEncoder) AppendArrayBegin() error { 302 enc.jsonDepth++ 303 return enc.jsonEncoder.AppendArrayBegin() 304 } 305 306 // AppendArrayEnd appends an array end character. 307 func (enc *FlatEncoder) AppendArrayEnd() error { 308 enc.jsonDepth-- 309 err := enc.jsonEncoder.AppendArrayEnd() 310 if enc.jsonDepth == 0 { 311 enc.jsonEncoder.Reset() 312 } 313 return err 314 } 315 316 // AppendKey appends a key. 317 func (enc *FlatEncoder) AppendKey(key string) error { 318 if enc.jsonDepth > 0 { 319 return enc.jsonEncoder.AppendKey(key) 320 } 321 if enc.init { 322 enc.buf.WriteString(enc.separator) 323 } 324 enc.init = true 325 enc.buf.WriteString(key) 326 enc.buf.WriteByte('=') 327 return nil 328 } 329 330 // AppendBool appends a bool. 331 func (enc *FlatEncoder) AppendBool(v bool) error { 332 if enc.jsonDepth > 0 { 333 return enc.jsonEncoder.AppendBool(v) 334 } 335 enc.buf.WriteString(strconv.FormatBool(v)) 336 return nil 337 } 338 339 // AppendInt64 appends a int64. 340 func (enc *FlatEncoder) AppendInt64(v int64) error { 341 if enc.jsonDepth > 0 { 342 return enc.jsonEncoder.AppendInt64(v) 343 } 344 enc.buf.WriteString(strconv.FormatInt(v, 10)) 345 return nil 346 } 347 348 // AppendUint64 appends a uint64. 349 func (enc *FlatEncoder) AppendUint64(v uint64) error { 350 if enc.jsonDepth > 0 { 351 return enc.jsonEncoder.AppendUint64(v) 352 } 353 enc.buf.WriteString(strconv.FormatUint(v, 10)) 354 return nil 355 } 356 357 // AppendFloat64 appends a float64. 358 func (enc *FlatEncoder) AppendFloat64(v float64) error { 359 if enc.jsonDepth > 0 { 360 return enc.jsonEncoder.AppendFloat64(v) 361 } 362 enc.buf.WriteString(strconv.FormatFloat(v, 'f', -1, 64)) 363 return nil 364 } 365 366 // AppendString appends a string. 367 func (enc *FlatEncoder) AppendString(v string) error { 368 if enc.jsonDepth > 0 { 369 return enc.jsonEncoder.AppendString(v) 370 } 371 enc.buf.WriteString(v) 372 return nil 373 } 374 375 // AppendReflect appends an interface{}. 376 func (enc *FlatEncoder) AppendReflect(v interface{}) error { 377 if enc.jsonDepth > 0 { 378 return enc.jsonEncoder.AppendReflect(v) 379 } 380 b, err := json.Marshal(v) 381 if err != nil { 382 return err 383 } 384 enc.buf.Write(b) 385 return nil 386 }