1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20package thrift 21 22import ( 23 "context" 24 "encoding/base64" 25 "fmt" 26) 27 28const ( 29 THRIFT_JSON_PROTOCOL_VERSION = 1 30) 31 32// for references to _ParseContext see tsimplejson_protocol.go 33 34// JSON protocol implementation for thrift. 35// Utilizes Simple JSON protocol 36type TJSONProtocol struct { 37 *TSimpleJSONProtocol 38} 39 40// Constructor 41func NewTJSONProtocol(t TTransport) *TJSONProtocol { 42 v := &TJSONProtocol{TSimpleJSONProtocol: NewTSimpleJSONProtocol(t)} 43 v.parseContextStack.push(_CONTEXT_IN_TOPLEVEL) 44 v.dumpContext.push(_CONTEXT_IN_TOPLEVEL) 45 return v 46} 47 48// Factory 49type TJSONProtocolFactory struct{} 50 51func (p *TJSONProtocolFactory) GetProtocol(trans TTransport) TProtocol { 52 return NewTJSONProtocol(trans) 53} 54 55func NewTJSONProtocolFactory() *TJSONProtocolFactory { 56 return &TJSONProtocolFactory{} 57} 58 59func (p *TJSONProtocol) WriteMessageBegin(ctx context.Context, name string, typeId TMessageType, seqId int32) error { 60 p.resetContextStack() // THRIFT-3735 61 if e := p.OutputListBegin(); e != nil { 62 return e 63 } 64 if e := p.WriteI32(ctx, THRIFT_JSON_PROTOCOL_VERSION); e != nil { 65 return e 66 } 67 if e := p.WriteString(ctx, name); e != nil { 68 return e 69 } 70 if e := p.WriteByte(ctx, int8(typeId)); e != nil { 71 return e 72 } 73 if e := p.WriteI32(ctx, seqId); e != nil { 74 return e 75 } 76 return nil 77} 78 79func (p *TJSONProtocol) WriteMessageEnd(ctx context.Context) error { 80 return p.OutputListEnd() 81} 82 83func (p *TJSONProtocol) WriteStructBegin(ctx context.Context, name string) error { 84 if e := p.OutputObjectBegin(); e != nil { 85 return e 86 } 87 return nil 88} 89 90func (p *TJSONProtocol) WriteStructEnd(ctx context.Context) error { 91 return p.OutputObjectEnd() 92} 93 94func (p *TJSONProtocol) WriteFieldBegin(ctx context.Context, name string, typeId TType, id int16) error { 95 if e := p.WriteI16(ctx, id); e != nil { 96 return e 97 } 98 if e := p.OutputObjectBegin(); e != nil { 99 return e 100 } 101 s, e1 := p.TypeIdToString(typeId) 102 if e1 != nil { 103 return e1 104 } 105 if e := p.WriteString(ctx, s); e != nil { 106 return e 107 } 108 return nil 109} 110 111func (p *TJSONProtocol) WriteFieldEnd(ctx context.Context) error { 112 return p.OutputObjectEnd() 113} 114 115func (p *TJSONProtocol) WriteFieldStop(ctx context.Context) error { return nil } 116 117func (p *TJSONProtocol) WriteMapBegin(ctx context.Context, keyType TType, valueType TType, size int) error { 118 if e := p.OutputListBegin(); e != nil { 119 return e 120 } 121 s, e1 := p.TypeIdToString(keyType) 122 if e1 != nil { 123 return e1 124 } 125 if e := p.WriteString(ctx, s); e != nil { 126 return e 127 } 128 s, e1 = p.TypeIdToString(valueType) 129 if e1 != nil { 130 return e1 131 } 132 if e := p.WriteString(ctx, s); e != nil { 133 return e 134 } 135 if e := p.WriteI64(ctx, int64(size)); e != nil { 136 return e 137 } 138 return p.OutputObjectBegin() 139} 140 141func (p *TJSONProtocol) WriteMapEnd(ctx context.Context) error { 142 if e := p.OutputObjectEnd(); e != nil { 143 return e 144 } 145 return p.OutputListEnd() 146} 147 148func (p *TJSONProtocol) WriteListBegin(ctx context.Context, elemType TType, size int) error { 149 return p.OutputElemListBegin(elemType, size) 150} 151 152func (p *TJSONProtocol) WriteListEnd(ctx context.Context) error { 153 return p.OutputListEnd() 154} 155 156func (p *TJSONProtocol) WriteSetBegin(ctx context.Context, elemType TType, size int) error { 157 return p.OutputElemListBegin(elemType, size) 158} 159 160func (p *TJSONProtocol) WriteSetEnd(ctx context.Context) error { 161 return p.OutputListEnd() 162} 163 164func (p *TJSONProtocol) WriteBool(ctx context.Context, b bool) error { 165 if b { 166 return p.WriteI32(ctx, 1) 167 } 168 return p.WriteI32(ctx, 0) 169} 170 171func (p *TJSONProtocol) WriteByte(ctx context.Context, b int8) error { 172 return p.WriteI32(ctx, int32(b)) 173} 174 175func (p *TJSONProtocol) WriteI16(ctx context.Context, v int16) error { 176 return p.WriteI32(ctx, int32(v)) 177} 178 179func (p *TJSONProtocol) WriteI32(ctx context.Context, v int32) error { 180 return p.OutputI64(int64(v)) 181} 182 183func (p *TJSONProtocol) WriteI64(ctx context.Context, v int64) error { 184 return p.OutputI64(int64(v)) 185} 186 187func (p *TJSONProtocol) WriteDouble(ctx context.Context, v float64) error { 188 return p.OutputF64(v) 189} 190 191func (p *TJSONProtocol) WriteString(ctx context.Context, v string) error { 192 return p.OutputString(v) 193} 194 195func (p *TJSONProtocol) WriteBinary(ctx context.Context, v []byte) error { 196 // JSON library only takes in a string, 197 // not an arbitrary byte array, to ensure bytes are transmitted 198 // efficiently we must convert this into a valid JSON string 199 // therefore we use base64 encoding to avoid excessive escaping/quoting 200 if e := p.OutputPreValue(); e != nil { 201 return e 202 } 203 if _, e := p.write(JSON_QUOTE_BYTES); e != nil { 204 return NewTProtocolException(e) 205 } 206 writer := base64.NewEncoder(base64.StdEncoding, p.writer) 207 if _, e := writer.Write(v); e != nil { 208 p.writer.Reset(p.trans) // THRIFT-3735 209 return NewTProtocolException(e) 210 } 211 if e := writer.Close(); e != nil { 212 return NewTProtocolException(e) 213 } 214 if _, e := p.write(JSON_QUOTE_BYTES); e != nil { 215 return NewTProtocolException(e) 216 } 217 return p.OutputPostValue() 218} 219 220// Reading methods. 221func (p *TJSONProtocol) ReadMessageBegin(ctx context.Context) (name string, typeId TMessageType, seqId int32, err error) { 222 p.resetContextStack() // THRIFT-3735 223 if isNull, err := p.ParseListBegin(); isNull || err != nil { 224 return name, typeId, seqId, err 225 } 226 version, err := p.ReadI32(ctx) 227 if err != nil { 228 return name, typeId, seqId, err 229 } 230 if version != THRIFT_JSON_PROTOCOL_VERSION { 231 e := fmt.Errorf("Unknown Protocol version %d, expected version %d", version, THRIFT_JSON_PROTOCOL_VERSION) 232 return name, typeId, seqId, NewTProtocolExceptionWithType(INVALID_DATA, e) 233 234 } 235 if name, err = p.ReadString(ctx); err != nil { 236 return name, typeId, seqId, err 237 } 238 bTypeId, err := p.ReadByte(ctx) 239 typeId = TMessageType(bTypeId) 240 if err != nil { 241 return name, typeId, seqId, err 242 } 243 if seqId, err = p.ReadI32(ctx); err != nil { 244 return name, typeId, seqId, err 245 } 246 return name, typeId, seqId, nil 247} 248 249func (p *TJSONProtocol) ReadMessageEnd(ctx context.Context) error { 250 err := p.ParseListEnd() 251 return err 252} 253 254func (p *TJSONProtocol) ReadStructBegin(ctx context.Context) (name string, err error) { 255 _, err = p.ParseObjectStart() 256 return "", err 257} 258 259func (p *TJSONProtocol) ReadStructEnd(ctx context.Context) error { 260 return p.ParseObjectEnd() 261} 262 263func (p *TJSONProtocol) ReadFieldBegin(ctx context.Context) (string, TType, int16, error) { 264 b, _ := p.reader.Peek(1) 265 if len(b) < 1 || b[0] == JSON_RBRACE[0] || b[0] == JSON_RBRACKET[0] { 266 return "", STOP, -1, nil 267 } 268 fieldId, err := p.ReadI16(ctx) 269 if err != nil { 270 return "", STOP, fieldId, err 271 } 272 if _, err = p.ParseObjectStart(); err != nil { 273 return "", STOP, fieldId, err 274 } 275 sType, err := p.ReadString(ctx) 276 if err != nil { 277 return "", STOP, fieldId, err 278 } 279 fType, err := p.StringToTypeId(sType) 280 return "", fType, fieldId, err 281} 282 283func (p *TJSONProtocol) ReadFieldEnd(ctx context.Context) error { 284 return p.ParseObjectEnd() 285} 286 287func (p *TJSONProtocol) ReadMapBegin(ctx context.Context) (keyType TType, valueType TType, size int, e error) { 288 if isNull, e := p.ParseListBegin(); isNull || e != nil { 289 return VOID, VOID, 0, e 290 } 291 292 // read keyType 293 sKeyType, e := p.ReadString(ctx) 294 if e != nil { 295 return keyType, valueType, size, e 296 } 297 keyType, e = p.StringToTypeId(sKeyType) 298 if e != nil { 299 return keyType, valueType, size, e 300 } 301 302 // read valueType 303 sValueType, e := p.ReadString(ctx) 304 if e != nil { 305 return keyType, valueType, size, e 306 } 307 valueType, e = p.StringToTypeId(sValueType) 308 if e != nil { 309 return keyType, valueType, size, e 310 } 311 312 // read size 313 iSize, err := p.ReadI64(ctx) 314 if err != nil { 315 return keyType, valueType, size, err 316 } 317 err = checkSizeForProtocol(int32(iSize), p.cfg) 318 if err != nil { 319 return keyType, valueType, 0, err 320 } 321 size = int(iSize) 322 323 _, e = p.ParseObjectStart() 324 return keyType, valueType, size, e 325} 326 327func (p *TJSONProtocol) ReadMapEnd(ctx context.Context) error { 328 e := p.ParseObjectEnd() 329 if e != nil { 330 return e 331 } 332 return p.ParseListEnd() 333} 334 335func (p *TJSONProtocol) ReadListBegin(ctx context.Context) (elemType TType, size int, e error) { 336 return p.ParseElemListBegin() 337} 338 339func (p *TJSONProtocol) ReadListEnd(ctx context.Context) error { 340 return p.ParseListEnd() 341} 342 343func (p *TJSONProtocol) ReadSetBegin(ctx context.Context) (elemType TType, size int, e error) { 344 return p.ParseElemListBegin() 345} 346 347func (p *TJSONProtocol) ReadSetEnd(ctx context.Context) error { 348 return p.ParseListEnd() 349} 350 351func (p *TJSONProtocol) ReadBool(ctx context.Context) (bool, error) { 352 value, err := p.ReadI32(ctx) 353 return (value != 0), err 354} 355 356func (p *TJSONProtocol) ReadByte(ctx context.Context) (int8, error) { 357 v, err := p.ReadI64(ctx) 358 return int8(v), err 359} 360 361func (p *TJSONProtocol) ReadI16(ctx context.Context) (int16, error) { 362 v, err := p.ReadI64(ctx) 363 return int16(v), err 364} 365 366func (p *TJSONProtocol) ReadI32(ctx context.Context) (int32, error) { 367 v, err := p.ReadI64(ctx) 368 return int32(v), err 369} 370 371func (p *TJSONProtocol) ReadI64(ctx context.Context) (int64, error) { 372 v, _, err := p.ParseI64() 373 return v, err 374} 375 376func (p *TJSONProtocol) ReadDouble(ctx context.Context) (float64, error) { 377 v, _, err := p.ParseF64() 378 return v, err 379} 380 381func (p *TJSONProtocol) ReadString(ctx context.Context) (string, error) { 382 var v string 383 if err := p.ParsePreValue(); err != nil { 384 return v, err 385 } 386 f, _ := p.reader.Peek(1) 387 if len(f) > 0 && f[0] == JSON_QUOTE { 388 p.reader.ReadByte() 389 value, err := p.ParseStringBody() 390 v = value 391 if err != nil { 392 return v, err 393 } 394 } else if len(f) > 0 && f[0] == JSON_NULL[0] { 395 b := make([]byte, len(JSON_NULL)) 396 _, err := p.reader.Read(b) 397 if err != nil { 398 return v, NewTProtocolException(err) 399 } 400 if string(b) != string(JSON_NULL) { 401 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) 402 return v, NewTProtocolExceptionWithType(INVALID_DATA, e) 403 } 404 } else { 405 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) 406 return v, NewTProtocolExceptionWithType(INVALID_DATA, e) 407 } 408 return v, p.ParsePostValue() 409} 410 411func (p *TJSONProtocol) ReadBinary(ctx context.Context) ([]byte, error) { 412 var v []byte 413 if err := p.ParsePreValue(); err != nil { 414 return nil, err 415 } 416 f, _ := p.reader.Peek(1) 417 if len(f) > 0 && f[0] == JSON_QUOTE { 418 p.reader.ReadByte() 419 value, err := p.ParseBase64EncodedBody() 420 v = value 421 if err != nil { 422 return v, err 423 } 424 } else if len(f) > 0 && f[0] == JSON_NULL[0] { 425 b := make([]byte, len(JSON_NULL)) 426 _, err := p.reader.Read(b) 427 if err != nil { 428 return v, NewTProtocolException(err) 429 } 430 if string(b) != string(JSON_NULL) { 431 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(b)) 432 return v, NewTProtocolExceptionWithType(INVALID_DATA, e) 433 } 434 } else { 435 e := fmt.Errorf("Expected a JSON string, found unquoted data started with %s", string(f)) 436 return v, NewTProtocolExceptionWithType(INVALID_DATA, e) 437 } 438 439 return v, p.ParsePostValue() 440} 441 442func (p *TJSONProtocol) Flush(ctx context.Context) (err error) { 443 err = p.writer.Flush() 444 if err == nil { 445 err = p.trans.Flush(ctx) 446 } 447 return NewTProtocolException(err) 448} 449 450func (p *TJSONProtocol) Skip(ctx context.Context, fieldType TType) (err error) { 451 return SkipDefaultDepth(ctx, p, fieldType) 452} 453 454func (p *TJSONProtocol) Transport() TTransport { 455 return p.trans 456} 457 458func (p *TJSONProtocol) OutputElemListBegin(elemType TType, size int) error { 459 if e := p.OutputListBegin(); e != nil { 460 return e 461 } 462 s, e1 := p.TypeIdToString(elemType) 463 if e1 != nil { 464 return e1 465 } 466 if e := p.OutputString(s); e != nil { 467 return e 468 } 469 if e := p.OutputI64(int64(size)); e != nil { 470 return e 471 } 472 return nil 473} 474 475func (p *TJSONProtocol) ParseElemListBegin() (elemType TType, size int, e error) { 476 if isNull, e := p.ParseListBegin(); isNull || e != nil { 477 return VOID, 0, e 478 } 479 // We don't really use the ctx in ReadString implementation, 480 // so this is safe for now. 481 // We might want to add context to ParseElemListBegin if we start to use 482 // ctx in ReadString implementation in the future. 483 sElemType, err := p.ReadString(context.Background()) 484 if err != nil { 485 return VOID, size, err 486 } 487 elemType, err = p.StringToTypeId(sElemType) 488 if err != nil { 489 return elemType, size, err 490 } 491 nSize, _, err := p.ParseI64() 492 if err != nil { 493 return elemType, 0, err 494 } 495 err = checkSizeForProtocol(int32(nSize), p.cfg) 496 if err != nil { 497 return elemType, 0, err 498 } 499 size = int(nSize) 500 return elemType, size, nil 501} 502 503func (p *TJSONProtocol) TypeIdToString(fieldType TType) (string, error) { 504 switch byte(fieldType) { 505 case BOOL: 506 return "tf", nil 507 case BYTE: 508 return "i8", nil 509 case I16: 510 return "i16", nil 511 case I32: 512 return "i32", nil 513 case I64: 514 return "i64", nil 515 case DOUBLE: 516 return "dbl", nil 517 case STRING: 518 return "str", nil 519 case STRUCT: 520 return "rec", nil 521 case MAP: 522 return "map", nil 523 case SET: 524 return "set", nil 525 case LIST: 526 return "lst", nil 527 case UUID: 528 return "uid", nil 529 } 530 531 e := fmt.Errorf("Unknown fieldType: %d", int(fieldType)) 532 return "", NewTProtocolExceptionWithType(INVALID_DATA, e) 533} 534 535func (p *TJSONProtocol) StringToTypeId(fieldType string) (TType, error) { 536 switch fieldType { 537 case "tf": 538 return TType(BOOL), nil 539 case "i8": 540 return TType(BYTE), nil 541 case "i16": 542 return TType(I16), nil 543 case "i32": 544 return TType(I32), nil 545 case "i64": 546 return TType(I64), nil 547 case "dbl": 548 return TType(DOUBLE), nil 549 case "str": 550 return TType(STRING), nil 551 case "rec": 552 return TType(STRUCT), nil 553 case "map": 554 return TType(MAP), nil 555 case "set": 556 return TType(SET), nil 557 case "lst": 558 return TType(LIST), nil 559 case "uid": 560 return TType(UUID), nil 561 } 562 563 e := fmt.Errorf("Unknown type identifier: %s", fieldType) 564 return TType(STOP), NewTProtocolExceptionWithType(INVALID_DATA, e) 565} 566 567var _ TConfigurationSetter = (*TJSONProtocol)(nil) 568