1// Copyright 2019 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package protojson 6 7import ( 8 "bytes" 9 "fmt" 10 "strconv" 11 "strings" 12 "time" 13 14 "google.golang.org/protobuf/internal/detectknown" 15 "google.golang.org/protobuf/internal/encoding/json" 16 "google.golang.org/protobuf/internal/errors" 17 "google.golang.org/protobuf/internal/fieldnum" 18 "google.golang.org/protobuf/internal/strs" 19 "google.golang.org/protobuf/proto" 20 pref "google.golang.org/protobuf/reflect/protoreflect" 21) 22 23// isCustomType returns true if type name has special JSON conversion rules. 24// The list of custom types here has to match the ones in marshalCustomType and 25// unmarshalCustomType. 26func isCustomType(name pref.FullName) bool { 27 switch detectknown.Which(name) { 28 case detectknown.AnyProto: 29 case detectknown.TimestampProto: 30 case detectknown.DurationProto: 31 case detectknown.WrappersProto: 32 case detectknown.StructProto: 33 case detectknown.FieldMaskProto: 34 case detectknown.EmptyProto: 35 default: 36 return false 37 } 38 return true 39} 40 41// marshalCustomType marshals given well-known type message that have special 42// JSON conversion rules. It needs to be a message type where isCustomType 43// returns true, else it will panic. 44func (e encoder) marshalCustomType(m pref.Message) error { 45 name := m.Descriptor().FullName() 46 switch detectknown.Which(name) { 47 case detectknown.AnyProto: 48 return e.marshalAny(m) 49 case detectknown.TimestampProto: 50 return e.marshalTimestamp(m) 51 case detectknown.DurationProto: 52 return e.marshalDuration(m) 53 case detectknown.WrappersProto: 54 return e.marshalWrapperType(m) 55 case detectknown.StructProto: 56 return e.marshalStructType(m) 57 case detectknown.FieldMaskProto: 58 return e.marshalFieldMask(m) 59 case detectknown.EmptyProto: 60 return e.marshalEmpty(m) 61 default: 62 panic(fmt.Sprintf("%s does not have a custom marshaler", name)) 63 } 64} 65 66// unmarshalCustomType unmarshals given well-known type message that have 67// special JSON conversion rules. It needs to be a message type where 68// isCustomType returns true, else it will panic. 69func (d decoder) unmarshalCustomType(m pref.Message) error { 70 name := m.Descriptor().FullName() 71 switch detectknown.Which(name) { 72 case detectknown.AnyProto: 73 return d.unmarshalAny(m) 74 case detectknown.TimestampProto: 75 return d.unmarshalTimestamp(m) 76 case detectknown.DurationProto: 77 return d.unmarshalDuration(m) 78 case detectknown.WrappersProto: 79 return d.unmarshalWrapperType(m) 80 case detectknown.StructProto: 81 return d.unmarshalStructType(m) 82 case detectknown.FieldMaskProto: 83 return d.unmarshalFieldMask(m) 84 case detectknown.EmptyProto: 85 return d.unmarshalEmpty(m) 86 default: 87 panic(fmt.Sprintf("%s does not have a custom unmarshaler", name)) 88 } 89} 90 91// The JSON representation of an Any message uses the regular representation of 92// the deserialized, embedded message, with an additional field `@type` which 93// contains the type URL. If the embedded message type is well-known and has a 94// custom JSON representation, that representation will be embedded adding a 95// field `value` which holds the custom JSON in addition to the `@type` field. 96 97func (e encoder) marshalAny(m pref.Message) error { 98 fds := m.Descriptor().Fields() 99 fdType := fds.ByNumber(fieldnum.Any_TypeUrl) 100 fdValue := fds.ByNumber(fieldnum.Any_Value) 101 102 // Start writing the JSON object. 103 e.StartObject() 104 defer e.EndObject() 105 106 if !m.Has(fdType) { 107 if !m.Has(fdValue) { 108 // If message is empty, marshal out empty JSON object. 109 return nil 110 } else { 111 // Return error if type_url field is not set, but value is set. 112 return errors.New("%s: type_url is not set", m.Descriptor().FullName()) 113 } 114 } 115 116 typeVal := m.Get(fdType) 117 valueVal := m.Get(fdValue) 118 119 // Marshal out @type field. 120 typeURL := typeVal.String() 121 e.WriteName("@type") 122 if err := e.WriteString(typeURL); err != nil { 123 return err 124 } 125 126 // Resolve the type in order to unmarshal value field. 127 emt, err := e.opts.Resolver.FindMessageByURL(typeURL) 128 if err != nil { 129 return errors.New("%s: unable to resolve %q: %v", m.Descriptor().FullName(), typeURL, err) 130 } 131 132 em := emt.New() 133 err = proto.UnmarshalOptions{ 134 AllowPartial: true, // never check required fields inside an Any 135 Resolver: e.opts.Resolver, 136 }.Unmarshal(valueVal.Bytes(), em.Interface()) 137 if err != nil { 138 return errors.New("%s: unable to unmarshal %q: %v", m.Descriptor().FullName(), typeURL, err) 139 } 140 141 // If type of value has custom JSON encoding, marshal out a field "value" 142 // with corresponding custom JSON encoding of the embedded message as a 143 // field. 144 if isCustomType(emt.Descriptor().FullName()) { 145 e.WriteName("value") 146 return e.marshalCustomType(em) 147 } 148 149 // Else, marshal out the embedded message's fields in this Any object. 150 if err := e.marshalFields(em); err != nil { 151 return err 152 } 153 154 return nil 155} 156 157func (d decoder) unmarshalAny(m pref.Message) error { 158 // Peek to check for json.ObjectOpen to avoid advancing a read. 159 start, err := d.Peek() 160 if err != nil { 161 return err 162 } 163 if start.Kind() != json.ObjectOpen { 164 return d.unexpectedTokenError(start) 165 } 166 167 // Use another decoder to parse the unread bytes for @type field. This 168 // avoids advancing a read from current decoder because the current JSON 169 // object may contain the fields of the embedded type. 170 dec := decoder{d.Clone(), UnmarshalOptions{}} 171 tok, err := findTypeURL(dec) 172 switch err { 173 case errEmptyObject: 174 // An empty JSON object translates to an empty Any message. 175 d.Read() // Read json.ObjectOpen. 176 d.Read() // Read json.ObjectClose. 177 return nil 178 179 case errMissingType: 180 if d.opts.DiscardUnknown { 181 // Treat all fields as unknowns, similar to an empty object. 182 return d.skipJSONValue() 183 } 184 // Use start.Pos() for line position. 185 return d.newError(start.Pos(), err.Error()) 186 187 default: 188 if err != nil { 189 return err 190 } 191 } 192 193 typeURL := tok.ParsedString() 194 emt, err := d.opts.Resolver.FindMessageByURL(typeURL) 195 if err != nil { 196 return d.newError(tok.Pos(), "unable to resolve %v: %q", tok.RawString(), err) 197 } 198 199 // Create new message for the embedded message type and unmarshal into it. 200 em := emt.New() 201 if isCustomType(emt.Descriptor().FullName()) { 202 // If embedded message is a custom type, 203 // unmarshal the JSON "value" field into it. 204 if err := d.unmarshalAnyValue(em); err != nil { 205 return err 206 } 207 } else { 208 // Else unmarshal the current JSON object into it. 209 if err := d.unmarshalMessage(em, true); err != nil { 210 return err 211 } 212 } 213 // Serialize the embedded message and assign the resulting bytes to the 214 // proto value field. 215 b, err := proto.MarshalOptions{ 216 AllowPartial: true, // No need to check required fields inside an Any. 217 Deterministic: true, 218 }.Marshal(em.Interface()) 219 if err != nil { 220 return d.newError(start.Pos(), "error in marshaling Any.value field: %v", err) 221 } 222 223 fds := m.Descriptor().Fields() 224 fdType := fds.ByNumber(fieldnum.Any_TypeUrl) 225 fdValue := fds.ByNumber(fieldnum.Any_Value) 226 227 m.Set(fdType, pref.ValueOfString(typeURL)) 228 m.Set(fdValue, pref.ValueOfBytes(b)) 229 return nil 230} 231 232var errEmptyObject = fmt.Errorf(`empty object`) 233var errMissingType = fmt.Errorf(`missing "@type" field`) 234 235// findTypeURL returns the token for the "@type" field value from the given 236// JSON bytes. It is expected that the given bytes start with json.ObjectOpen. 237// It returns errEmptyObject if the JSON object is empty or errMissingType if 238// @type field does not exist. It returns other error if the @type field is not 239// valid or other decoding issues. 240func findTypeURL(d decoder) (json.Token, error) { 241 var typeURL string 242 var typeTok json.Token 243 numFields := 0 244 // Skip start object. 245 d.Read() 246 247Loop: 248 for { 249 tok, err := d.Read() 250 if err != nil { 251 return json.Token{}, err 252 } 253 254 switch tok.Kind() { 255 case json.ObjectClose: 256 if typeURL == "" { 257 // Did not find @type field. 258 if numFields > 0 { 259 return json.Token{}, errMissingType 260 } 261 return json.Token{}, errEmptyObject 262 } 263 break Loop 264 265 case json.Name: 266 numFields++ 267 if tok.Name() != "@type" { 268 // Skip value. 269 if err := d.skipJSONValue(); err != nil { 270 return json.Token{}, err 271 } 272 continue 273 } 274 275 // Return error if this was previously set already. 276 if typeURL != "" { 277 return json.Token{}, d.newError(tok.Pos(), `duplicate "@type" field`) 278 } 279 // Read field value. 280 tok, err := d.Read() 281 if err != nil { 282 return json.Token{}, err 283 } 284 if tok.Kind() != json.String { 285 return json.Token{}, d.newError(tok.Pos(), `@type field value is not a string: %v`, tok.RawString()) 286 } 287 typeURL = tok.ParsedString() 288 if typeURL == "" { 289 return json.Token{}, d.newError(tok.Pos(), `@type field contains empty value`) 290 } 291 typeTok = tok 292 } 293 } 294 295 return typeTok, nil 296} 297 298// skipJSONValue parses a JSON value (null, boolean, string, number, object and 299// array) in order to advance the read to the next JSON value. It relies on 300// the decoder returning an error if the types are not in valid sequence. 301func (d decoder) skipJSONValue() error { 302 tok, err := d.Read() 303 if err != nil { 304 return err 305 } 306 // Only need to continue reading for objects and arrays. 307 switch tok.Kind() { 308 case json.ObjectOpen: 309 for { 310 tok, err := d.Read() 311 if err != nil { 312 return err 313 } 314 switch tok.Kind() { 315 case json.ObjectClose: 316 return nil 317 case json.Name: 318 // Skip object field value. 319 if err := d.skipJSONValue(); err != nil { 320 return err 321 } 322 } 323 } 324 325 case json.ArrayOpen: 326 for { 327 tok, err := d.Peek() 328 if err != nil { 329 return err 330 } 331 switch tok.Kind() { 332 case json.ArrayClose: 333 d.Read() 334 return nil 335 default: 336 // Skip array item. 337 if err := d.skipJSONValue(); err != nil { 338 return err 339 } 340 } 341 } 342 } 343 return nil 344} 345 346// unmarshalAnyValue unmarshals the given custom-type message from the JSON 347// object's "value" field. 348func (d decoder) unmarshalAnyValue(m pref.Message) error { 349 // Skip ObjectOpen, and start reading the fields. 350 d.Read() 351 352 var found bool // Used for detecting duplicate "value". 353 for { 354 tok, err := d.Read() 355 if err != nil { 356 return err 357 } 358 switch tok.Kind() { 359 case json.ObjectClose: 360 if !found { 361 return d.newError(tok.Pos(), `missing "value" field`) 362 } 363 return nil 364 365 case json.Name: 366 switch tok.Name() { 367 case "@type": 368 // Skip the value as this was previously parsed already. 369 d.Read() 370 371 case "value": 372 if found { 373 return d.newError(tok.Pos(), `duplicate "value" field`) 374 } 375 // Unmarshal the field value into the given message. 376 if err := d.unmarshalCustomType(m); err != nil { 377 return err 378 } 379 found = true 380 381 default: 382 if d.opts.DiscardUnknown { 383 if err := d.skipJSONValue(); err != nil { 384 return err 385 } 386 continue 387 } 388 return d.newError(tok.Pos(), "unknown field %v", tok.RawString()) 389 } 390 } 391 } 392} 393 394// Wrapper types are encoded as JSON primitives like string, number or boolean. 395 396// The "value" field has the same field number for all wrapper types. 397const wrapperFieldNumber = fieldnum.BoolValue_Value 398 399func (e encoder) marshalWrapperType(m pref.Message) error { 400 fd := m.Descriptor().Fields().ByNumber(wrapperFieldNumber) 401 val := m.Get(fd) 402 return e.marshalSingular(val, fd) 403} 404 405func (d decoder) unmarshalWrapperType(m pref.Message) error { 406 fd := m.Descriptor().Fields().ByNumber(wrapperFieldNumber) 407 val, err := d.unmarshalScalar(fd) 408 if err != nil { 409 return err 410 } 411 m.Set(fd, val) 412 return nil 413} 414 415// The JSON representation for Empty is an empty JSON object. 416 417func (e encoder) marshalEmpty(pref.Message) error { 418 e.StartObject() 419 e.EndObject() 420 return nil 421} 422 423func (d decoder) unmarshalEmpty(pref.Message) error { 424 tok, err := d.Read() 425 if err != nil { 426 return err 427 } 428 if tok.Kind() != json.ObjectOpen { 429 return d.unexpectedTokenError(tok) 430 } 431 432 for { 433 tok, err := d.Read() 434 if err != nil { 435 return err 436 } 437 switch tok.Kind() { 438 case json.ObjectClose: 439 return nil 440 441 case json.Name: 442 if d.opts.DiscardUnknown { 443 if err := d.skipJSONValue(); err != nil { 444 return err 445 } 446 continue 447 } 448 return d.newError(tok.Pos(), "unknown field %v", tok.RawString()) 449 450 default: 451 return d.unexpectedTokenError(tok) 452 } 453 } 454} 455 456func (e encoder) marshalStructType(m pref.Message) error { 457 switch m.Descriptor().Name() { 458 case "Struct": 459 return e.marshalStruct(m) 460 case "ListValue": 461 return e.marshalListValue(m) 462 case "Value": 463 return e.marshalKnownValue(m) 464 default: 465 panic(fmt.Sprintf("invalid struct type: %v", m.Descriptor().FullName())) 466 } 467} 468 469func (d decoder) unmarshalStructType(m pref.Message) error { 470 switch m.Descriptor().Name() { 471 case "Struct": 472 return d.unmarshalStruct(m) 473 case "ListValue": 474 return d.unmarshalListValue(m) 475 case "Value": 476 return d.unmarshalKnownValue(m) 477 default: 478 panic(fmt.Sprintf("invalid struct type: %v", m.Descriptor().FullName())) 479 } 480} 481 482// The JSON representation for Struct is a JSON object that contains the encoded 483// Struct.fields map and follows the serialization rules for a map. 484 485func (e encoder) marshalStruct(m pref.Message) error { 486 fd := m.Descriptor().Fields().ByNumber(fieldnum.Struct_Fields) 487 return e.marshalMap(m.Get(fd).Map(), fd) 488} 489 490func (d decoder) unmarshalStruct(m pref.Message) error { 491 fd := m.Descriptor().Fields().ByNumber(fieldnum.Struct_Fields) 492 return d.unmarshalMap(m.Mutable(fd).Map(), fd) 493} 494 495// The JSON representation for ListValue is JSON array that contains the encoded 496// ListValue.values repeated field and follows the serialization rules for a 497// repeated field. 498 499func (e encoder) marshalListValue(m pref.Message) error { 500 fd := m.Descriptor().Fields().ByNumber(fieldnum.ListValue_Values) 501 return e.marshalList(m.Get(fd).List(), fd) 502} 503 504func (d decoder) unmarshalListValue(m pref.Message) error { 505 fd := m.Descriptor().Fields().ByNumber(fieldnum.ListValue_Values) 506 return d.unmarshalList(m.Mutable(fd).List(), fd) 507} 508 509// The JSON representation for a Value is dependent on the oneof field that is 510// set. Each of the field in the oneof has its own custom serialization rule. A 511// Value message needs to be a oneof field set, else it is an error. 512 513func (e encoder) marshalKnownValue(m pref.Message) error { 514 od := m.Descriptor().Oneofs().ByName("kind") 515 fd := m.WhichOneof(od) 516 if fd == nil { 517 return errors.New("%s: none of the oneof fields is set", m.Descriptor().FullName()) 518 } 519 return e.marshalSingular(m.Get(fd), fd) 520} 521 522func (d decoder) unmarshalKnownValue(m pref.Message) error { 523 tok, err := d.Peek() 524 if err != nil { 525 return err 526 } 527 528 var fd pref.FieldDescriptor 529 var val pref.Value 530 switch tok.Kind() { 531 case json.Null: 532 d.Read() 533 fd = m.Descriptor().Fields().ByNumber(fieldnum.Value_NullValue) 534 val = pref.ValueOfEnum(0) 535 536 case json.Bool: 537 tok, err := d.Read() 538 if err != nil { 539 return err 540 } 541 fd = m.Descriptor().Fields().ByNumber(fieldnum.Value_BoolValue) 542 val = pref.ValueOfBool(tok.Bool()) 543 544 case json.Number: 545 tok, err := d.Read() 546 if err != nil { 547 return err 548 } 549 fd = m.Descriptor().Fields().ByNumber(fieldnum.Value_NumberValue) 550 var ok bool 551 val, ok = unmarshalFloat(tok, 64) 552 if !ok { 553 return d.newError(tok.Pos(), "invalid google.protobuf.Value: %v", tok.RawString()) 554 } 555 556 case json.String: 557 // A JSON string may have been encoded from the number_value field, 558 // e.g. "NaN", "Infinity", etc. Parsing a proto double type also allows 559 // for it to be in JSON string form. Given this custom encoding spec, 560 // however, there is no way to identify that and hence a JSON string is 561 // always assigned to the string_value field, which means that certain 562 // encoding cannot be parsed back to the same field. 563 tok, err := d.Read() 564 if err != nil { 565 return err 566 } 567 fd = m.Descriptor().Fields().ByNumber(fieldnum.Value_StringValue) 568 val = pref.ValueOfString(tok.ParsedString()) 569 570 case json.ObjectOpen: 571 fd = m.Descriptor().Fields().ByNumber(fieldnum.Value_StructValue) 572 val = m.NewField(fd) 573 if err := d.unmarshalStruct(val.Message()); err != nil { 574 return err 575 } 576 577 case json.ArrayOpen: 578 fd = m.Descriptor().Fields().ByNumber(fieldnum.Value_ListValue) 579 val = m.NewField(fd) 580 if err := d.unmarshalListValue(val.Message()); err != nil { 581 return err 582 } 583 584 default: 585 return d.newError(tok.Pos(), "invalid google.protobuf.Value: %v", tok.RawString()) 586 } 587 588 m.Set(fd, val) 589 return nil 590} 591 592// The JSON representation for a Duration is a JSON string that ends in the 593// suffix "s" (indicating seconds) and is preceded by the number of seconds, 594// with nanoseconds expressed as fractional seconds. 595// 596// Durations less than one second are represented with a 0 seconds field and a 597// positive or negative nanos field. For durations of one second or more, a 598// non-zero value for the nanos field must be of the same sign as the seconds 599// field. 600// 601// Duration.seconds must be from -315,576,000,000 to +315,576,000,000 inclusive. 602// Duration.nanos must be from -999,999,999 to +999,999,999 inclusive. 603 604const ( 605 secondsInNanos = 999999999 606 maxSecondsInDuration = 315576000000 607) 608 609func (e encoder) marshalDuration(m pref.Message) error { 610 fds := m.Descriptor().Fields() 611 fdSeconds := fds.ByNumber(fieldnum.Duration_Seconds) 612 fdNanos := fds.ByNumber(fieldnum.Duration_Nanos) 613 614 secsVal := m.Get(fdSeconds) 615 nanosVal := m.Get(fdNanos) 616 secs := secsVal.Int() 617 nanos := nanosVal.Int() 618 if secs < -maxSecondsInDuration || secs > maxSecondsInDuration { 619 return errors.New("%s: seconds out of range %v", m.Descriptor().FullName(), secs) 620 } 621 if nanos < -secondsInNanos || nanos > secondsInNanos { 622 return errors.New("%s: nanos out of range %v", m.Descriptor().FullName(), nanos) 623 } 624 if (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0) { 625 return errors.New("%s: signs of seconds and nanos do not match", m.Descriptor().FullName()) 626 } 627 // Generated output always contains 0, 3, 6, or 9 fractional digits, 628 // depending on required precision, followed by the suffix "s". 629 f := "%d.%09d" 630 if nanos < 0 { 631 nanos = -nanos 632 if secs == 0 { 633 f = "-%d.%09d" 634 } 635 } 636 x := fmt.Sprintf(f, secs, nanos) 637 x = strings.TrimSuffix(x, "000") 638 x = strings.TrimSuffix(x, "000") 639 x = strings.TrimSuffix(x, ".000") 640 e.WriteString(x + "s") 641 return nil 642} 643 644func (d decoder) unmarshalDuration(m pref.Message) error { 645 tok, err := d.Read() 646 if err != nil { 647 return err 648 } 649 if tok.Kind() != json.String { 650 return d.unexpectedTokenError(tok) 651 } 652 653 secs, nanos, ok := parseDuration(tok.ParsedString()) 654 if !ok { 655 return d.newError(tok.Pos(), "invalid google.protobuf.Duration value %v", tok.RawString()) 656 } 657 // Validate seconds. No need to validate nanos because parseDuration would 658 // have covered that already. 659 if secs < -maxSecondsInDuration || secs > maxSecondsInDuration { 660 return d.newError(tok.Pos(), "google.protobuf.Duration value out of range: %v", tok.RawString()) 661 } 662 663 fds := m.Descriptor().Fields() 664 fdSeconds := fds.ByNumber(fieldnum.Duration_Seconds) 665 fdNanos := fds.ByNumber(fieldnum.Duration_Nanos) 666 667 m.Set(fdSeconds, pref.ValueOfInt64(secs)) 668 m.Set(fdNanos, pref.ValueOfInt32(nanos)) 669 return nil 670} 671 672// parseDuration parses the given input string for seconds and nanoseconds value 673// for the Duration JSON format. The format is a decimal number with a suffix 674// 's'. It can have optional plus/minus sign. There needs to be at least an 675// integer or fractional part. Fractional part is limited to 9 digits only for 676// nanoseconds precision, regardless of whether there are trailing zero digits. 677// Example values are 1s, 0.1s, 1.s, .1s, +1s, -1s, -.1s. 678func parseDuration(input string) (int64, int32, bool) { 679 b := []byte(input) 680 size := len(b) 681 if size < 2 { 682 return 0, 0, false 683 } 684 if b[size-1] != 's' { 685 return 0, 0, false 686 } 687 b = b[:size-1] 688 689 // Read optional plus/minus symbol. 690 var neg bool 691 switch b[0] { 692 case '-': 693 neg = true 694 b = b[1:] 695 case '+': 696 b = b[1:] 697 } 698 if len(b) == 0 { 699 return 0, 0, false 700 } 701 702 // Read the integer part. 703 var intp []byte 704 switch { 705 case b[0] == '0': 706 b = b[1:] 707 708 case '1' <= b[0] && b[0] <= '9': 709 intp = b[0:] 710 b = b[1:] 711 n := 1 712 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' { 713 n++ 714 b = b[1:] 715 } 716 intp = intp[:n] 717 718 case b[0] == '.': 719 // Continue below. 720 721 default: 722 return 0, 0, false 723 } 724 725 hasFrac := false 726 var frac [9]byte 727 if len(b) > 0 { 728 if b[0] != '.' { 729 return 0, 0, false 730 } 731 // Read the fractional part. 732 b = b[1:] 733 n := 0 734 for len(b) > 0 && n < 9 && '0' <= b[0] && b[0] <= '9' { 735 frac[n] = b[0] 736 n++ 737 b = b[1:] 738 } 739 // It is not valid if there are more bytes left. 740 if len(b) > 0 { 741 return 0, 0, false 742 } 743 // Pad fractional part with 0s. 744 for i := n; i < 9; i++ { 745 frac[i] = '0' 746 } 747 hasFrac = true 748 } 749 750 var secs int64 751 if len(intp) > 0 { 752 var err error 753 secs, err = strconv.ParseInt(string(intp), 10, 64) 754 if err != nil { 755 return 0, 0, false 756 } 757 } 758 759 var nanos int64 760 if hasFrac { 761 nanob := bytes.TrimLeft(frac[:], "0") 762 if len(nanob) > 0 { 763 var err error 764 nanos, err = strconv.ParseInt(string(nanob), 10, 32) 765 if err != nil { 766 return 0, 0, false 767 } 768 } 769 } 770 771 if neg { 772 if secs > 0 { 773 secs = -secs 774 } 775 if nanos > 0 { 776 nanos = -nanos 777 } 778 } 779 return secs, int32(nanos), true 780} 781 782// The JSON representation for a Timestamp is a JSON string in the RFC 3339 783// format, i.e. "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" where 784// {year} is always expressed using four digits while {month}, {day}, {hour}, 785// {min}, and {sec} are zero-padded to two digits each. The fractional seconds, 786// which can go up to 9 digits, up to 1 nanosecond resolution, is optional. The 787// "Z" suffix indicates the timezone ("UTC"); the timezone is required. Encoding 788// should always use UTC (as indicated by "Z") and a decoder should be able to 789// accept both UTC and other timezones (as indicated by an offset). 790// 791// Timestamp.seconds must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z 792// inclusive. 793// Timestamp.nanos must be from 0 to 999,999,999 inclusive. 794 795const ( 796 maxTimestampSeconds = 253402300799 797 minTimestampSeconds = -62135596800 798) 799 800func (e encoder) marshalTimestamp(m pref.Message) error { 801 fds := m.Descriptor().Fields() 802 fdSeconds := fds.ByNumber(fieldnum.Timestamp_Seconds) 803 fdNanos := fds.ByNumber(fieldnum.Timestamp_Nanos) 804 805 secsVal := m.Get(fdSeconds) 806 nanosVal := m.Get(fdNanos) 807 secs := secsVal.Int() 808 nanos := nanosVal.Int() 809 if secs < minTimestampSeconds || secs > maxTimestampSeconds { 810 return errors.New("%s: seconds out of range %v", m.Descriptor().FullName(), secs) 811 } 812 if nanos < 0 || nanos > secondsInNanos { 813 return errors.New("%s: nanos out of range %v", m.Descriptor().FullName(), nanos) 814 } 815 // Uses RFC 3339, where generated output will be Z-normalized and uses 0, 3, 816 // 6 or 9 fractional digits. 817 t := time.Unix(secs, nanos).UTC() 818 x := t.Format("2006-01-02T15:04:05.000000000") 819 x = strings.TrimSuffix(x, "000") 820 x = strings.TrimSuffix(x, "000") 821 x = strings.TrimSuffix(x, ".000") 822 e.WriteString(x + "Z") 823 return nil 824} 825 826func (d decoder) unmarshalTimestamp(m pref.Message) error { 827 tok, err := d.Read() 828 if err != nil { 829 return err 830 } 831 if tok.Kind() != json.String { 832 return d.unexpectedTokenError(tok) 833 } 834 835 t, err := time.Parse(time.RFC3339Nano, tok.ParsedString()) 836 if err != nil { 837 return d.newError(tok.Pos(), "invalid google.protobuf.Timestamp value %v", tok.RawString()) 838 } 839 // Validate seconds. No need to validate nanos because time.Parse would have 840 // covered that already. 841 secs := t.Unix() 842 if secs < minTimestampSeconds || secs > maxTimestampSeconds { 843 return d.newError(tok.Pos(), "google.protobuf.Timestamp value out of range: %v", tok.RawString()) 844 } 845 846 fds := m.Descriptor().Fields() 847 fdSeconds := fds.ByNumber(fieldnum.Timestamp_Seconds) 848 fdNanos := fds.ByNumber(fieldnum.Timestamp_Nanos) 849 850 m.Set(fdSeconds, pref.ValueOfInt64(secs)) 851 m.Set(fdNanos, pref.ValueOfInt32(int32(t.Nanosecond()))) 852 return nil 853} 854 855// The JSON representation for a FieldMask is a JSON string where paths are 856// separated by a comma. Fields name in each path are converted to/from 857// lower-camel naming conventions. Encoding should fail if the path name would 858// end up differently after a round-trip. 859 860func (e encoder) marshalFieldMask(m pref.Message) error { 861 fd := m.Descriptor().Fields().ByNumber(fieldnum.FieldMask_Paths) 862 list := m.Get(fd).List() 863 paths := make([]string, 0, list.Len()) 864 865 for i := 0; i < list.Len(); i++ { 866 s := list.Get(i).String() 867 // Return error if conversion to camelCase is not reversible. 868 cc := strs.JSONCamelCase(s) 869 if s != strs.JSONSnakeCase(cc) { 870 return errors.New("%s.paths contains irreversible value %q", m.Descriptor().FullName(), s) 871 } 872 paths = append(paths, cc) 873 } 874 875 e.WriteString(strings.Join(paths, ",")) 876 return nil 877} 878 879func (d decoder) unmarshalFieldMask(m pref.Message) error { 880 tok, err := d.Read() 881 if err != nil { 882 return err 883 } 884 if tok.Kind() != json.String { 885 return d.unexpectedTokenError(tok) 886 } 887 str := strings.TrimSpace(tok.ParsedString()) 888 if str == "" { 889 return nil 890 } 891 paths := strings.Split(str, ",") 892 893 fd := m.Descriptor().Fields().ByNumber(fieldnum.FieldMask_Paths) 894 list := m.Mutable(fd).List() 895 896 for _, s := range paths { 897 s = strings.TrimSpace(s) 898 // Convert to snake_case. Unlike encoding, no validation is done because 899 // it is not possible to know the original path names. 900 list.Append(pref.ValueOfString(strs.JSONSnakeCase(s))) 901 } 902 return nil 903} 904