github.com/matrixorigin/matrixone@v1.2.0/pkg/container/bytejson/bytejson.go (about) 1 // Copyright 2022 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package bytejson 16 17 import ( 18 "bytes" 19 "encoding/json" 20 "fmt" 21 "math" 22 "sort" 23 "strconv" 24 "strings" 25 26 "github.com/matrixorigin/matrixone/pkg/common/moerr" 27 "github.com/matrixorigin/matrixone/pkg/common/util" 28 ) 29 30 func (bj ByteJson) String() string { 31 ret, _ := bj.MarshalJSON() 32 return string(ret) 33 } 34 35 func (bj ByteJson) Unquote() (string, error) { 36 if bj.Type != TpCodeString { 37 return bj.String(), nil 38 } 39 str := bj.GetString() 40 if len(str) < 2 || (str[0] != '"' || str[len(str)-1] != '"') { 41 return string(str), nil 42 } 43 str = str[1 : len(str)-1] 44 var sb strings.Builder 45 for i := 0; i < len(str); i++ { 46 if str[i] != '\\' { 47 sb.WriteByte(str[i]) 48 continue 49 } 50 i++ 51 if trans, ok := escapedChars[str[i]]; ok { 52 sb.WriteByte(trans) 53 continue 54 } 55 if str[i] == 'u' { // transform unicode to utf8 56 if i+4 > len(str) { 57 return "", moerr.NewInvalidInputNoCtx("invalid unicode") 58 } 59 unicodeStr := string(str[i-1 : i+5]) 60 content := strings.Replace(strconv.Quote(unicodeStr), `\\u`, `\u`, -1) 61 text, err := strconv.Unquote(content) 62 if err != nil { 63 return "", moerr.NewInvalidInputNoCtx("invalid unicode") 64 } 65 sb.WriteString(text) 66 i += 4 67 continue 68 } 69 sb.WriteByte(str[i]) 70 } 71 return sb.String(), nil 72 } 73 74 // MarshalJSON transform bytejson to []byte,for visible 75 func (bj ByteJson) MarshalJSON() ([]byte, error) { 76 ret := make([]byte, 0, len(bj.Data)*3/2) 77 return bj.to(ret) 78 } 79 80 // Marshal transform bytejson to []byte,for storage 81 func (bj ByteJson) Marshal() ([]byte, error) { 82 buf := make([]byte, len(bj.Data)+1) 83 buf[0] = byte(bj.Type) 84 copy(buf[1:], bj.Data) 85 return buf, nil 86 } 87 88 // Unmarshal transform storage []byte to bytejson 89 func (bj *ByteJson) Unmarshal(buf []byte) error { 90 //TODO add validate checker 91 bj.Type = TpCode(buf[0]) 92 bj.Data = buf[1:] 93 return nil 94 } 95 96 // UnmarshalJSON transform visible []byte to bytejson 97 func (bj *ByteJson) UnmarshalJSON(data []byte) error { 98 var decoder = json.NewDecoder(bytes.NewReader(data)) 99 decoder.UseNumber() 100 var in interface{} 101 err := decoder.Decode(&in) 102 if err != nil { 103 return nil 104 } 105 buf := make([]byte, 0, len(data)) 106 if tpCode, buf, err := addElem(buf, in); err != nil { 107 return err 108 } else { 109 bj.Data = buf 110 bj.Type = tpCode 111 } 112 return nil 113 } 114 115 func (bj *ByteJson) UnmarshalObject(obj interface{}) (err error) { 116 buf := make([]byte, 0, 64) 117 var tpCode TpCode 118 if tpCode, buf, err = addElem(buf, obj); err != nil { 119 return 120 } 121 bj.Type = tpCode 122 bj.Data = buf 123 return 124 } 125 126 func (bj ByteJson) IsNull() bool { 127 return bj.Type == TpCodeLiteral && bj.Data[0] == LiteralNull 128 } 129 130 func (bj ByteJson) GetElemCnt() int { 131 return int(endian.Uint32(bj.Data)) 132 } 133 134 func (bj ByteJson) GetInt64() int64 { 135 return int64(bj.GetUint64()) 136 } 137 func (bj ByteJson) GetUint64() uint64 { 138 return endian.Uint64(bj.Data) 139 } 140 141 func (bj ByteJson) GetFloat64() float64 { 142 return math.Float64frombits(bj.GetUint64()) 143 } 144 145 func (bj ByteJson) GetString() []byte { 146 num, length := calStrLen(bj.Data) 147 return bj.Data[length : length+num] 148 } 149 150 func (bj ByteJson) to(buf []byte) ([]byte, error) { 151 var err error 152 switch bj.Type { 153 case TpCodeArray: 154 buf, err = bj.toArray(buf) 155 case TpCodeObject: 156 buf, err = bj.toObject(buf) 157 case TpCodeInt64: 158 buf = bj.toInt64(buf) 159 case TpCodeUint64: 160 buf = bj.toUint64(buf) 161 case TpCodeLiteral: 162 buf = bj.toLiteral(buf) 163 case TpCodeFloat64: 164 buf, err = bj.toFloat64(buf) 165 case TpCodeString: 166 buf = bj.toString(buf) 167 default: 168 err = moerr.NewInvalidInputNoCtx("invalid json type '%v'", bj.Type) 169 } 170 return buf, err 171 } 172 173 func (bj ByteJson) toArray(buf []byte) ([]byte, error) { 174 cnt := bj.GetElemCnt() 175 buf = append(buf, '[') 176 var err error 177 for i := 0; i < cnt; i++ { 178 if i != 0 { 179 buf = append(buf, ", "...) 180 } 181 buf, err = bj.getArrayElem(i).to(buf) 182 if err != nil { 183 return nil, err 184 } 185 } 186 return append(buf, ']'), nil 187 } 188 189 func (bj ByteJson) toObject(buf []byte) ([]byte, error) { 190 cnt := bj.GetElemCnt() 191 buf = append(buf, '{') 192 for i := 0; i < cnt; i++ { 193 if i != 0 { 194 buf = append(buf, ", "...) 195 } 196 var err error 197 buf = toString(buf, bj.getObjectKey(i)) 198 buf = append(buf, ": "...) 199 buf, err = bj.getObjectVal(i).to(buf) 200 if err != nil { 201 return nil, err 202 } 203 } 204 return append(buf, '}'), nil 205 } 206 207 func (bj ByteJson) toInt64(buf []byte) []byte { 208 return strconv.AppendInt(buf, bj.GetInt64(), 10) 209 } 210 func (bj ByteJson) toUint64(buf []byte) []byte { 211 return strconv.AppendUint(buf, bj.GetUint64(), 10) 212 } 213 214 func (bj ByteJson) toLiteral(buf []byte) []byte { 215 litTp := bj.Data[0] 216 switch litTp { 217 case LiteralNull: 218 buf = append(buf, "null"...) 219 case LiteralTrue: 220 buf = append(buf, "true"...) 221 case LiteralFalse: 222 buf = append(buf, "false"...) 223 default: 224 panic(fmt.Sprintf("invalid literal type:%d", litTp)) 225 } 226 return buf 227 } 228 229 func (bj ByteJson) toFloat64(buf []byte) ([]byte, error) { 230 f := bj.GetFloat64() 231 err := checkFloat64(f) 232 if err != nil { 233 return nil, err 234 } 235 // https://github.com/golang/go/issues/14135 236 var format byte 237 abs := math.Abs(f) 238 if abs == 0 || 1e-6 <= abs && abs < 1e21 { 239 format = 'f' 240 } else { 241 format = 'e' 242 } 243 buf = strconv.AppendFloat(buf, f, format, -1, 64) 244 return buf, nil 245 } 246 247 // transform byte string to visible string 248 func (bj ByteJson) toString(buf []byte) []byte { 249 data := bj.GetString() 250 return toString(buf, data) 251 } 252 253 func (bj ByteJson) getObjectKey(i int) []byte { 254 keyOff := int(endian.Uint32(bj.Data[headerSize+i*keyEntrySize:])) 255 keyLen := int(endian.Uint16(bj.Data[headerSize+i*keyEntrySize+keyOriginOff:])) 256 return bj.Data[keyOff : keyOff+keyLen] 257 } 258 259 func (bj ByteJson) getArrayElem(i int) ByteJson { 260 return bj.getValEntry(headerSize + i*valEntrySize) 261 } 262 263 func (bj ByteJson) getObjectVal(i int) ByteJson { 264 cnt := bj.GetElemCnt() 265 return bj.getValEntry(headerSize + cnt*keyEntrySize + i*valEntrySize) 266 } 267 268 func (bj ByteJson) getValEntry(off int) ByteJson { 269 tpCode := bj.Data[off] 270 valOff := endian.Uint32(bj.Data[off+valTypeSize:]) 271 switch TpCode(tpCode) { 272 case TpCodeLiteral: 273 return ByteJson{Type: TpCodeLiteral, Data: bj.Data[off+valTypeSize : off+valTypeSize+1]} 274 case TpCodeUint64, TpCodeInt64, TpCodeFloat64: 275 return ByteJson{Type: TpCode(tpCode), Data: bj.Data[valOff : valOff+numberSize]} 276 case TpCodeString: 277 num, length := calStrLen(bj.Data[valOff:]) 278 totalLen := uint32(num) + uint32(length) 279 return ByteJson{Type: TpCode(tpCode), Data: bj.Data[valOff : valOff+totalLen]} 280 } 281 dataBytes := endian.Uint32(bj.Data[valOff+docSizeOff:]) 282 return ByteJson{Type: TpCode(tpCode), Data: bj.Data[valOff : valOff+dataBytes]} 283 } 284 285 func (bj ByteJson) queryValByKey(key []byte) ByteJson { 286 cnt := bj.GetElemCnt() 287 idx := sort.Search(cnt, func(i int) bool { 288 return bytes.Compare(bj.getObjectKey(i), key) >= 0 289 }) 290 if idx >= cnt || !bytes.Equal(bj.getObjectKey(idx), key) { 291 dt := make([]byte, 1) 292 dt[0] = LiteralNull 293 return ByteJson{ 294 Type: TpCodeLiteral, 295 Data: dt, 296 } 297 } 298 return bj.getObjectVal(idx) 299 } 300 301 func (bj ByteJson) query(cur []ByteJson, path *Path) []ByteJson { 302 if path.empty() { 303 cur = append(cur, bj) 304 return cur 305 } 306 sub, nPath := path.step() 307 308 if sub.tp == subPathDoubleStar { 309 cur = bj.query(cur, &nPath) 310 if bj.Type == TpCodeObject { 311 cnt := bj.GetElemCnt() 312 for i := 0; i < cnt; i++ { 313 cur = bj.getObjectVal(i).query(cur, path) // take care here, the argument is path,not nPath 314 } 315 } else if bj.Type == TpCodeArray { 316 cnt := bj.GetElemCnt() 317 for i := 0; i < cnt; i++ { 318 cur = bj.getArrayElem(i).query(cur, path) // take care here, the argument is path,not nPath 319 } 320 } 321 return cur 322 } 323 324 if bj.Type == TpCodeObject { 325 switch sub.tp { 326 case subPathIdx: 327 start, _, _ := sub.idx.genIndex(1) 328 if start == 0 { 329 cur = bj.query(cur, &nPath) 330 } 331 case subPathRange: 332 se := sub.iRange.genRange(bj.GetElemCnt()) 333 if se[0] == 0 { 334 cur = bj.query(cur, &nPath) 335 } 336 case subPathKey: 337 cnt := bj.GetElemCnt() 338 if sub.key == "*" { 339 for i := 0; i < cnt; i++ { 340 cur = bj.getObjectVal(i).query(cur, &nPath) 341 } 342 } else { 343 tmp := bj.queryValByKey(util.UnsafeStringToBytes(sub.key)) 344 cur = tmp.query(cur, &nPath) 345 } 346 } 347 return cur 348 } 349 350 if bj.Type == TpCodeArray { 351 cnt := bj.GetElemCnt() 352 switch sub.tp { 353 case subPathIdx: 354 idx, _, last := sub.idx.genIndex(cnt) 355 if last && idx < 0 || cnt <= idx { 356 tmp := ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}} 357 cur = append(cur, tmp) 358 return cur 359 } 360 if idx == subPathIdxALL { 361 for i := 0; i < cnt; i++ { 362 cur = bj.getArrayElem(i).query(cur, &nPath) 363 } 364 } else { 365 cur = bj.getArrayElem(idx).query(cur, &nPath) 366 } 367 case subPathRange: 368 se := sub.iRange.genRange(cnt) 369 if se[0] == subPathIdxErr { 370 tmp := ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}} 371 cur = append(cur, tmp) 372 return cur 373 } 374 for i := se[0]; i <= se[1]; i++ { 375 cur = bj.getArrayElem(i).query(cur, &nPath) 376 } 377 } 378 } 379 return cur 380 } 381 func (bj ByteJson) Query(paths []*Path) *ByteJson { 382 out := make([]ByteJson, 0, len(paths)) 383 for _, path := range paths { 384 tmp := bj.query(nil, path) 385 if len(tmp) > 0 { 386 allNull := checkAllNull(tmp) 387 if !allNull { 388 out = append(out, tmp...) 389 } 390 } 391 } 392 if len(out) == 0 { 393 return &ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}} 394 } 395 if len(out) == 1 && len(paths) == 1 { 396 return &out[0] 397 } 398 allNull := checkAllNull(out) 399 if allNull { 400 return &ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}} 401 } 402 return mergeToArray(out) 403 } 404 405 func (bj ByteJson) canUnnest() bool { 406 return bj.Type == TpCodeArray || bj.Type == TpCodeObject 407 } 408 409 func (bj ByteJson) queryWithSubPath(keys []string, vals []ByteJson, path *Path, pathStr string) ([]string, []ByteJson) { 410 if path.empty() { 411 keys = append(keys, pathStr) 412 vals = append(vals, bj) 413 return keys, vals 414 } 415 sub, nPath := path.step() 416 if sub.tp == subPathDoubleStar { 417 keys, vals = bj.queryWithSubPath(keys, vals, &nPath, pathStr) 418 if bj.Type == TpCodeObject { 419 cnt := bj.GetElemCnt() 420 for i := 0; i < cnt; i++ { 421 newPathStr := fmt.Sprintf("%s.%s", pathStr, bj.getObjectKey(i)) 422 keys, vals = bj.getObjectVal(i).queryWithSubPath(keys, vals, path, newPathStr) // take care here, the argument is path,not nPath 423 } 424 } else if bj.Type == TpCodeArray { 425 cnt := bj.GetElemCnt() 426 for i := 0; i < cnt; i++ { 427 newPathStr := fmt.Sprintf("%s[%d]", pathStr, i) 428 keys, vals = bj.getArrayElem(i).queryWithSubPath(keys, vals, path, newPathStr) // take care here, the argument is path,not nPath 429 } 430 } 431 return keys, vals 432 } 433 if bj.Type == TpCodeObject { 434 cnt := bj.GetElemCnt() 435 switch sub.tp { 436 case subPathIdx: 437 start, _, _ := sub.idx.genIndex(1) 438 if start == 0 { 439 newPathStr := fmt.Sprintf("%s[%d]", pathStr, start) 440 keys, vals = bj.queryWithSubPath(keys, vals, &nPath, newPathStr) 441 } 442 case subPathRange: 443 se := sub.iRange.genRange(cnt) 444 if se[0] == 0 { 445 newPathStr := fmt.Sprintf("%s[%d]", pathStr, se[0]) 446 keys, vals = bj.queryWithSubPath(keys, vals, &nPath, newPathStr) 447 } 448 case subPathKey: 449 if sub.key == "*" { 450 for i := 0; i < cnt; i++ { 451 newPathStr := fmt.Sprintf("%s.%s", pathStr, bj.getObjectKey(i)) 452 keys, vals = bj.getObjectVal(i).queryWithSubPath(keys, vals, &nPath, newPathStr) 453 } 454 } else { 455 tmp := bj.queryValByKey(util.UnsafeStringToBytes(sub.key)) 456 newPathStr := fmt.Sprintf("%s.%s", pathStr, sub.key) 457 keys, vals = tmp.queryWithSubPath(keys, vals, &nPath, newPathStr) 458 } 459 } 460 } 461 if bj.Type == TpCodeArray { 462 cnt := bj.GetElemCnt() 463 switch sub.tp { 464 case subPathIdx: 465 idx, _, last := sub.idx.genIndex(cnt) 466 if last && idx < 0 { 467 tmp := ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}} 468 newPathStr := fmt.Sprintf("%s[%d]", pathStr, sub.idx.num) 469 keys = append(keys, newPathStr) 470 vals = append(vals, tmp) 471 return keys, vals 472 } 473 if idx == subPathIdxALL { 474 for i := 0; i < cnt; i++ { 475 newPathStr := fmt.Sprintf("%s[%d]", pathStr, i) 476 keys, vals = bj.getArrayElem(i).queryWithSubPath(keys, vals, &nPath, newPathStr) 477 } 478 } else { 479 newPathStr := fmt.Sprintf("%s[%d]", pathStr, idx) 480 keys, vals = bj.getArrayElem(idx).queryWithSubPath(keys, vals, &nPath, newPathStr) 481 } 482 case subPathRange: 483 se := sub.iRange.genRange(cnt) 484 if se[0] == subPathIdxErr { 485 tmp := ByteJson{Type: TpCodeLiteral, Data: []byte{LiteralNull}} 486 newPathStr := fmt.Sprintf("%s[%d to %d]", pathStr, sub.iRange.start.num, sub.iRange.end.num) 487 keys = append(keys, newPathStr) 488 vals = append(vals, tmp) 489 return keys, vals 490 } 491 for i := se[0]; i <= se[1]; i++ { 492 newPathStr := fmt.Sprintf("%s[%d]", pathStr, i) 493 keys, vals = bj.getArrayElem(i).queryWithSubPath(keys, vals, &nPath, newPathStr) 494 } 495 } 496 } 497 return keys, vals 498 } 499 500 func (bj ByteJson) unnestWithParams(out []UnnestResult, outer, recursive bool, mode string, pathStr string, this *ByteJson, filterMap map[string]struct{}) []UnnestResult { 501 if !bj.canUnnest() { 502 index, key := genIndexOrKey(pathStr) 503 tmp := UnnestResult{} 504 genUnnestResult(tmp, index, key, util.UnsafeStringToBytes(pathStr), &bj, this, filterMap) 505 out = append(out, tmp) 506 return out 507 } 508 if bj.Type == TpCodeObject && mode != "array" { 509 cnt := bj.GetElemCnt() 510 for i := 0; i < cnt; i++ { 511 key := bj.getObjectKey(i) 512 val := bj.getObjectVal(i) 513 newPathStr := fmt.Sprintf("%s.%s", pathStr, key) 514 tmp := UnnestResult{} 515 genUnnestResult(tmp, nil, key, util.UnsafeStringToBytes(newPathStr), &val, this, filterMap) 516 out = append(out, tmp) 517 if val.canUnnest() && recursive { 518 out = val.unnestWithParams(out, outer, recursive, mode, newPathStr, &val, filterMap) 519 } 520 } 521 } 522 if bj.Type == TpCodeArray && mode != "object" { 523 cnt := bj.GetElemCnt() 524 for i := 0; i < cnt; i++ { 525 val := bj.getArrayElem(i) 526 newPathStr := fmt.Sprintf("%s[%d]", pathStr, i) 527 tmp := UnnestResult{} 528 genUnnestResult(tmp, util.UnsafeStringToBytes(strconv.Itoa(i)), nil, util.UnsafeStringToBytes(newPathStr), &val, this, filterMap) 529 out = append(out, tmp) 530 if val.canUnnest() && recursive { 531 out = val.unnestWithParams(out, outer, recursive, mode, newPathStr, &val, filterMap) 532 } 533 } 534 } 535 return out 536 } 537 538 func (bj ByteJson) unnest(out []UnnestResult, path *Path, outer, recursive bool, mode string, filterMap map[string]struct{}) ([]UnnestResult, error) { 539 540 keys := make([]string, 0, 1) 541 vals := make([]ByteJson, 0, 1) 542 keys, vals = bj.queryWithSubPath(keys, vals, path, "$") 543 if len(keys) != len(vals) { 544 return nil, moerr.NewInvalidInputNoCtx("len(key) and len(val) are not equal, len(key)=%d, len(val)=%d", len(keys), len(vals)) 545 } 546 for i := 0; i < len(keys); i++ { 547 if vals[i].canUnnest() { 548 out = vals[i].unnestWithParams(out, outer, recursive, mode, keys[i], &vals[i], filterMap) 549 } 550 } 551 if len(out) == 0 && outer { 552 for i := 0; i < len(keys); i++ { 553 tmp := UnnestResult{} 554 out = append(out, tmp) 555 } 556 if _, ok := filterMap["path"]; ok { 557 for i := 0; i < len(keys); i++ { 558 out[i]["path"] = util.UnsafeStringToBytes(keys[i]) 559 } 560 } 561 if _, ok := filterMap["this"]; ok { 562 for i := 0; i < len(vals); i++ { 563 dt, err := vals[i].Marshal() 564 if err != nil { 565 return nil, err 566 } 567 out[i]["this"] = dt 568 } 569 } 570 571 } 572 return out, nil 573 } 574 575 // Unnest returns a slice of UnnestResult, each UnnestResult contains filtered data, if param filters is nil, return all fields. 576 func (bj ByteJson) Unnest(path *Path, outer, recursive bool, mode string, filterMap map[string]struct{}) ([]UnnestResult, error) { 577 if !checkMode(mode) { 578 return nil, moerr.NewInvalidInputNoCtx("mode must be one of [object, array, both]") 579 } 580 out := make([]UnnestResult, 0, 1) 581 out, err := bj.unnest(out, path, outer, recursive, mode, filterMap) 582 return out, err 583 } 584 585 func genUnnestResult(res UnnestResult, index, key, path []byte, value, this *ByteJson, filterMap map[string]struct{}) UnnestResult { 586 if _, ok := filterMap["index"]; ok { 587 res["index"] = index 588 } 589 if _, ok := filterMap["key"]; ok { 590 res["key"] = key 591 } 592 if _, ok := filterMap["path"]; ok { 593 res["path"] = path 594 } 595 if _, ok := filterMap["value"]; ok { 596 dt, _ := value.Marshal() 597 res["value"] = dt 598 } 599 if _, ok := filterMap["this"]; ok { 600 dt, _ := this.Marshal() 601 res["this"] = dt 602 } 603 return res 604 } 605 606 func ParseJsonByteFromString(s string) ([]byte, error) { 607 var decoder = json.NewDecoder(strings.NewReader(s)) 608 decoder.UseNumber() 609 var in interface{} 610 err := decoder.Decode(&in) 611 if err != nil { 612 return nil, err 613 } 614 buf := make([]byte, 1, len(s)+1) 615 switch x := in.(type) { 616 case nil: 617 buf[0] = byte(TpCodeLiteral) 618 buf = append(buf, LiteralNull) 619 case bool: 620 buf[0] = byte(TpCodeLiteral) 621 lit := LiteralFalse 622 if x { 623 lit = LiteralTrue 624 } 625 buf = append(buf, lit) 626 case int64: 627 buf[0] = byte(TpCodeInt64) 628 buf = addUint64(buf, uint64(x)) 629 case uint64: 630 buf[0] = byte(TpCodeUint64) 631 buf = addUint64(buf, x) 632 case json.Number: 633 if strings.ContainsAny(string(x), "Ee.") { 634 val, err := x.Float64() 635 buf[0] = byte(TpCodeFloat64) 636 if err != nil { 637 return nil, moerr.NewInvalidInputNoCtx("json number %v", in) 638 } 639 if err = checkFloat64(val); err != nil { 640 return nil, err 641 } 642 return addFloat64(buf, val), nil 643 } 644 if val, err := x.Int64(); err == nil { 645 buf[0] = byte(TpCodeInt64) 646 return addInt64(buf, val), nil 647 } 648 if val, err := strconv.ParseUint(string(x), 10, 64); err == nil { 649 buf[0] = byte(TpCodeUint64) 650 return addUint64(buf, val), nil 651 } 652 if val, err := x.Float64(); err == nil { 653 buf[0] = byte(TpCodeFloat64) 654 if err = checkFloat64(val); err != nil { 655 return nil, err 656 } 657 return addFloat64(buf, val), nil 658 } 659 case string: 660 buf[0] = byte(TpCodeString) 661 buf = addString(buf, x) 662 case ByteJson: 663 buf[0] = byte(x.Type) 664 buf = append(buf, x.Data...) 665 case []interface{}: 666 buf[0] = byte(TpCodeArray) 667 buf, err = addArray(buf, x) 668 case map[string]interface{}: 669 buf[0] = byte(TpCodeObject) 670 buf, err = addObject(buf, x) 671 default: 672 return nil, moerr.NewInvalidInputNoCtx("json element %v", in) 673 } 674 return buf, err 675 }