1// Go support for Protocol Buffers - Google's data interchange format 2// 3// Copyright 2015 The Go Authors. All rights reserved. 4// https://github.com/golang/protobuf 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: 9// 10// * Redistributions of source code must retain the above copyright 11// notice, this list of conditions and the following disclaimer. 12// * Redistributions in binary form must reproduce the above 13// copyright notice, this list of conditions and the following disclaimer 14// in the documentation and/or other materials provided with the 15// distribution. 16// * Neither the name of Google Inc. nor the names of its 17// contributors may be used to endorse or promote products derived from 18// this software without specific prior written permission. 19// 20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32/* 33Package jsonpb provides marshaling and unmarshaling between protocol buffers and JSON. 34It follows the specification at https://developers.google.com/protocol-buffers/docs/proto3#json. 35 36This package produces a different output than the standard "encoding/json" package, 37which does not operate correctly on protocol buffers. 38*/ 39package jsonpb 40 41import ( 42 "bytes" 43 "encoding/json" 44 "errors" 45 "fmt" 46 "io" 47 "reflect" 48 "sort" 49 "strconv" 50 "strings" 51 "time" 52 53 "github.com/golang/protobuf/proto" 54) 55 56// Marshaler is a configurable object for converting between 57// protocol buffer objects and a JSON representation for them. 58type Marshaler struct { 59 // Whether to render enum values as integers, as opposed to string values. 60 EnumsAsInts bool 61 62 // Whether to render fields with zero values. 63 EmitDefaults bool 64 65 // A string to indent each level by. The presence of this field will 66 // also cause a space to appear between the field separator and 67 // value, and for newlines to be appear between fields and array 68 // elements. 69 Indent string 70 71 // Whether to use the original (.proto) name for fields. 72 OrigName bool 73} 74 75// Marshal marshals a protocol buffer into JSON. 76func (m *Marshaler) Marshal(out io.Writer, pb proto.Message) error { 77 writer := &errWriter{writer: out} 78 return m.marshalObject(writer, pb, "", "") 79} 80 81// MarshalToString converts a protocol buffer object to JSON string. 82func (m *Marshaler) MarshalToString(pb proto.Message) (string, error) { 83 var buf bytes.Buffer 84 if err := m.Marshal(&buf, pb); err != nil { 85 return "", err 86 } 87 return buf.String(), nil 88} 89 90type int32Slice []int32 91 92// For sorting extensions ids to ensure stable output. 93func (s int32Slice) Len() int { return len(s) } 94func (s int32Slice) Less(i, j int) bool { return s[i] < s[j] } 95func (s int32Slice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 96 97type wkt interface { 98 XXX_WellKnownType() string 99} 100 101// marshalObject writes a struct to the Writer. 102func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent, typeURL string) error { 103 s := reflect.ValueOf(v).Elem() 104 105 // Handle well-known types. 106 if wkt, ok := v.(wkt); ok { 107 switch wkt.XXX_WellKnownType() { 108 case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", 109 "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": 110 // "Wrappers use the same representation in JSON 111 // as the wrapped primitive type, ..." 112 sprop := proto.GetProperties(s.Type()) 113 return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent) 114 case "Any": 115 // Any is a bit more involved. 116 return m.marshalAny(out, v, indent) 117 case "Duration": 118 // "Generated output always contains 3, 6, or 9 fractional digits, 119 // depending on required precision." 120 s, ns := s.Field(0).Int(), s.Field(1).Int() 121 d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond 122 x := fmt.Sprintf("%.9f", d.Seconds()) 123 x = strings.TrimSuffix(x, "000") 124 x = strings.TrimSuffix(x, "000") 125 out.write(`"`) 126 out.write(x) 127 out.write(`s"`) 128 return out.err 129 case "Struct": 130 // Let marshalValue handle the `fields` map. 131 // TODO: pass the correct Properties if needed. 132 return m.marshalValue(out, &proto.Properties{}, s.Field(0), indent) 133 case "Timestamp": 134 // "RFC 3339, where generated output will always be Z-normalized 135 // and uses 3, 6 or 9 fractional digits." 136 s, ns := s.Field(0).Int(), s.Field(1).Int() 137 t := time.Unix(s, ns).UTC() 138 // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). 139 x := t.Format("2006-01-02T15:04:05.000000000") 140 x = strings.TrimSuffix(x, "000") 141 x = strings.TrimSuffix(x, "000") 142 out.write(`"`) 143 out.write(x) 144 out.write(`Z"`) 145 return out.err 146 case "Value": 147 // Value has a single oneof. 148 kind := s.Field(0) 149 if kind.IsNil() { 150 // "absence of any variant indicates an error" 151 return errors.New("nil Value") 152 } 153 // oneof -> *T -> T -> T.F 154 x := kind.Elem().Elem().Field(0) 155 // TODO: pass the correct Properties if needed. 156 return m.marshalValue(out, &proto.Properties{}, x, indent) 157 } 158 } 159 160 out.write("{") 161 if m.Indent != "" { 162 out.write("\n") 163 } 164 165 firstField := true 166 167 if typeURL != "" { 168 if err := m.marshalTypeURL(out, indent, typeURL); err != nil { 169 return err 170 } 171 firstField = false 172 } 173 174 for i := 0; i < s.NumField(); i++ { 175 value := s.Field(i) 176 valueField := s.Type().Field(i) 177 if strings.HasPrefix(valueField.Name, "XXX_") { 178 continue 179 } 180 181 // IsNil will panic on most value kinds. 182 switch value.Kind() { 183 case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: 184 if value.IsNil() { 185 continue 186 } 187 } 188 189 if !m.EmitDefaults { 190 switch value.Kind() { 191 case reflect.Bool: 192 if !value.Bool() { 193 continue 194 } 195 case reflect.Int32, reflect.Int64: 196 if value.Int() == 0 { 197 continue 198 } 199 case reflect.Uint32, reflect.Uint64: 200 if value.Uint() == 0 { 201 continue 202 } 203 case reflect.Float32, reflect.Float64: 204 if value.Float() == 0 { 205 continue 206 } 207 case reflect.String: 208 if value.Len() == 0 { 209 continue 210 } 211 } 212 } 213 214 // Oneof fields need special handling. 215 if valueField.Tag.Get("protobuf_oneof") != "" { 216 // value is an interface containing &T{real_value}. 217 sv := value.Elem().Elem() // interface -> *T -> T 218 value = sv.Field(0) 219 valueField = sv.Type().Field(0) 220 } 221 prop := jsonProperties(valueField, m.OrigName) 222 if !firstField { 223 m.writeSep(out) 224 } 225 if err := m.marshalField(out, prop, value, indent); err != nil { 226 return err 227 } 228 firstField = false 229 } 230 231 // Handle proto2 extensions. 232 if ep, ok := v.(proto.Message); ok { 233 extensions := proto.RegisteredExtensions(v) 234 // Sort extensions for stable output. 235 ids := make([]int32, 0, len(extensions)) 236 for id, desc := range extensions { 237 if !proto.HasExtension(ep, desc) { 238 continue 239 } 240 ids = append(ids, id) 241 } 242 sort.Sort(int32Slice(ids)) 243 for _, id := range ids { 244 desc := extensions[id] 245 if desc == nil { 246 // unknown extension 247 continue 248 } 249 ext, extErr := proto.GetExtension(ep, desc) 250 if extErr != nil { 251 return extErr 252 } 253 value := reflect.ValueOf(ext) 254 var prop proto.Properties 255 prop.Parse(desc.Tag) 256 prop.JSONName = fmt.Sprintf("[%s]", desc.Name) 257 if !firstField { 258 m.writeSep(out) 259 } 260 if err := m.marshalField(out, &prop, value, indent); err != nil { 261 return err 262 } 263 firstField = false 264 } 265 266 } 267 268 if m.Indent != "" { 269 out.write("\n") 270 out.write(indent) 271 } 272 out.write("}") 273 return out.err 274} 275 276func (m *Marshaler) writeSep(out *errWriter) { 277 if m.Indent != "" { 278 out.write(",\n") 279 } else { 280 out.write(",") 281 } 282} 283 284func (m *Marshaler) marshalAny(out *errWriter, any proto.Message, indent string) error { 285 // "If the Any contains a value that has a special JSON mapping, 286 // it will be converted as follows: {"@type": xxx, "value": yyy}. 287 // Otherwise, the value will be converted into a JSON object, 288 // and the "@type" field will be inserted to indicate the actual data type." 289 v := reflect.ValueOf(any).Elem() 290 turl := v.Field(0).String() 291 val := v.Field(1).Bytes() 292 293 // Only the part of type_url after the last slash is relevant. 294 mname := turl 295 if slash := strings.LastIndex(mname, "/"); slash >= 0 { 296 mname = mname[slash+1:] 297 } 298 mt := proto.MessageType(mname) 299 if mt == nil { 300 return fmt.Errorf("unknown message type %q", mname) 301 } 302 msg := reflect.New(mt.Elem()).Interface().(proto.Message) 303 if err := proto.Unmarshal(val, msg); err != nil { 304 return err 305 } 306 307 if _, ok := msg.(wkt); ok { 308 out.write("{") 309 if m.Indent != "" { 310 out.write("\n") 311 } 312 if err := m.marshalTypeURL(out, indent, turl); err != nil { 313 return err 314 } 315 m.writeSep(out) 316 if m.Indent != "" { 317 out.write(indent) 318 out.write(m.Indent) 319 out.write(`"value": `) 320 } else { 321 out.write(`"value":`) 322 } 323 if err := m.marshalObject(out, msg, indent+m.Indent, ""); err != nil { 324 return err 325 } 326 if m.Indent != "" { 327 out.write("\n") 328 out.write(indent) 329 } 330 out.write("}") 331 return out.err 332 } 333 334 return m.marshalObject(out, msg, indent, turl) 335} 336 337func (m *Marshaler) marshalTypeURL(out *errWriter, indent, typeURL string) error { 338 if m.Indent != "" { 339 out.write(indent) 340 out.write(m.Indent) 341 } 342 out.write(`"@type":`) 343 if m.Indent != "" { 344 out.write(" ") 345 } 346 b, err := json.Marshal(typeURL) 347 if err != nil { 348 return err 349 } 350 out.write(string(b)) 351 return out.err 352} 353 354// marshalField writes field description and value to the Writer. 355func (m *Marshaler) marshalField(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error { 356 if m.Indent != "" { 357 out.write(indent) 358 out.write(m.Indent) 359 } 360 out.write(`"`) 361 out.write(prop.JSONName) 362 out.write(`":`) 363 if m.Indent != "" { 364 out.write(" ") 365 } 366 if err := m.marshalValue(out, prop, v, indent); err != nil { 367 return err 368 } 369 return nil 370} 371 372// marshalValue writes the value to the Writer. 373func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v reflect.Value, indent string) error { 374 375 var err error 376 v = reflect.Indirect(v) 377 378 // Handle repeated elements. 379 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 { 380 out.write("[") 381 comma := "" 382 for i := 0; i < v.Len(); i++ { 383 sliceVal := v.Index(i) 384 out.write(comma) 385 if m.Indent != "" { 386 out.write("\n") 387 out.write(indent) 388 out.write(m.Indent) 389 out.write(m.Indent) 390 } 391 if err := m.marshalValue(out, prop, sliceVal, indent+m.Indent); err != nil { 392 return err 393 } 394 comma = "," 395 } 396 if m.Indent != "" { 397 out.write("\n") 398 out.write(indent) 399 out.write(m.Indent) 400 } 401 out.write("]") 402 return out.err 403 } 404 405 // Handle well-known types. 406 // Most are handled up in marshalObject (because 99% are messages). 407 type wkt interface { 408 XXX_WellKnownType() string 409 } 410 if wkt, ok := v.Interface().(wkt); ok { 411 switch wkt.XXX_WellKnownType() { 412 case "NullValue": 413 out.write("null") 414 return out.err 415 } 416 } 417 418 // Handle enumerations. 419 if !m.EnumsAsInts && prop.Enum != "" { 420 // Unknown enum values will are stringified by the proto library as their 421 // value. Such values should _not_ be quoted or they will be interpreted 422 // as an enum string instead of their value. 423 enumStr := v.Interface().(fmt.Stringer).String() 424 var valStr string 425 if v.Kind() == reflect.Ptr { 426 valStr = strconv.Itoa(int(v.Elem().Int())) 427 } else { 428 valStr = strconv.Itoa(int(v.Int())) 429 } 430 isKnownEnum := enumStr != valStr 431 if isKnownEnum { 432 out.write(`"`) 433 } 434 out.write(enumStr) 435 if isKnownEnum { 436 out.write(`"`) 437 } 438 return out.err 439 } 440 441 // Handle nested messages. 442 if v.Kind() == reflect.Struct { 443 return m.marshalObject(out, v.Addr().Interface().(proto.Message), indent+m.Indent, "") 444 } 445 446 // Handle maps. 447 // Since Go randomizes map iteration, we sort keys for stable output. 448 if v.Kind() == reflect.Map { 449 out.write(`{`) 450 keys := v.MapKeys() 451 sort.Sort(mapKeys(keys)) 452 for i, k := range keys { 453 if i > 0 { 454 out.write(`,`) 455 } 456 if m.Indent != "" { 457 out.write("\n") 458 out.write(indent) 459 out.write(m.Indent) 460 out.write(m.Indent) 461 } 462 463 b, err := json.Marshal(k.Interface()) 464 if err != nil { 465 return err 466 } 467 s := string(b) 468 469 // If the JSON is not a string value, encode it again to make it one. 470 if !strings.HasPrefix(s, `"`) { 471 b, err := json.Marshal(s) 472 if err != nil { 473 return err 474 } 475 s = string(b) 476 } 477 478 out.write(s) 479 out.write(`:`) 480 if m.Indent != "" { 481 out.write(` `) 482 } 483 484 if err := m.marshalValue(out, prop, v.MapIndex(k), indent+m.Indent); err != nil { 485 return err 486 } 487 } 488 if m.Indent != "" { 489 out.write("\n") 490 out.write(indent) 491 out.write(m.Indent) 492 } 493 out.write(`}`) 494 return out.err 495 } 496 497 // Default handling defers to the encoding/json library. 498 b, err := json.Marshal(v.Interface()) 499 if err != nil { 500 return err 501 } 502 needToQuote := string(b[0]) != `"` && (v.Kind() == reflect.Int64 || v.Kind() == reflect.Uint64) 503 if needToQuote { 504 out.write(`"`) 505 } 506 out.write(string(b)) 507 if needToQuote { 508 out.write(`"`) 509 } 510 return out.err 511} 512 513// Unmarshaler is a configurable object for converting from a JSON 514// representation to a protocol buffer object. 515type Unmarshaler struct { 516 // Whether to allow messages to contain unknown fields, as opposed to 517 // failing to unmarshal. 518 AllowUnknownFields bool 519} 520 521// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream. 522// This function is lenient and will decode any options permutations of the 523// related Marshaler. 524func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error { 525 inputValue := json.RawMessage{} 526 if err := dec.Decode(&inputValue); err != nil { 527 return err 528 } 529 return u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil) 530} 531 532// Unmarshal unmarshals a JSON object stream into a protocol 533// buffer. This function is lenient and will decode any options 534// permutations of the related Marshaler. 535func (u *Unmarshaler) Unmarshal(r io.Reader, pb proto.Message) error { 536 dec := json.NewDecoder(r) 537 return u.UnmarshalNext(dec, pb) 538} 539 540// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream. 541// This function is lenient and will decode any options permutations of the 542// related Marshaler. 543func UnmarshalNext(dec *json.Decoder, pb proto.Message) error { 544 return new(Unmarshaler).UnmarshalNext(dec, pb) 545} 546 547// Unmarshal unmarshals a JSON object stream into a protocol 548// buffer. This function is lenient and will decode any options 549// permutations of the related Marshaler. 550func Unmarshal(r io.Reader, pb proto.Message) error { 551 return new(Unmarshaler).Unmarshal(r, pb) 552} 553 554// UnmarshalString will populate the fields of a protocol buffer based 555// on a JSON string. This function is lenient and will decode any options 556// permutations of the related Marshaler. 557func UnmarshalString(str string, pb proto.Message) error { 558 return new(Unmarshaler).Unmarshal(strings.NewReader(str), pb) 559} 560 561// unmarshalValue converts/copies a value into the target. 562// prop may be nil. 563func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *proto.Properties) error { 564 targetType := target.Type() 565 566 // Allocate memory for pointer fields. 567 if targetType.Kind() == reflect.Ptr { 568 target.Set(reflect.New(targetType.Elem())) 569 return u.unmarshalValue(target.Elem(), inputValue, prop) 570 } 571 572 // Handle well-known types. 573 type wkt interface { 574 XXX_WellKnownType() string 575 } 576 if wkt, ok := target.Addr().Interface().(wkt); ok { 577 switch wkt.XXX_WellKnownType() { 578 case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", 579 "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": 580 // "Wrappers use the same representation in JSON 581 // as the wrapped primitive type, except that null is allowed." 582 // encoding/json will turn JSON `null` into Go `nil`, 583 // so we don't have to do any extra work. 584 return u.unmarshalValue(target.Field(0), inputValue, prop) 585 case "Any": 586 return fmt.Errorf("unmarshaling Any not supported yet") 587 case "Duration": 588 ivStr := string(inputValue) 589 if ivStr == "null" { 590 target.Field(0).SetInt(0) 591 target.Field(1).SetInt(0) 592 return nil 593 } 594 595 unq, err := strconv.Unquote(ivStr) 596 if err != nil { 597 return err 598 } 599 d, err := time.ParseDuration(unq) 600 if err != nil { 601 return fmt.Errorf("bad Duration: %v", err) 602 } 603 ns := d.Nanoseconds() 604 s := ns / 1e9 605 ns %= 1e9 606 target.Field(0).SetInt(s) 607 target.Field(1).SetInt(ns) 608 return nil 609 case "Timestamp": 610 ivStr := string(inputValue) 611 if ivStr == "null" { 612 target.Field(0).SetInt(0) 613 target.Field(1).SetInt(0) 614 return nil 615 } 616 617 unq, err := strconv.Unquote(ivStr) 618 if err != nil { 619 return err 620 } 621 t, err := time.Parse(time.RFC3339Nano, unq) 622 if err != nil { 623 return fmt.Errorf("bad Timestamp: %v", err) 624 } 625 target.Field(0).SetInt(int64(t.Unix())) 626 target.Field(1).SetInt(int64(t.Nanosecond())) 627 return nil 628 } 629 } 630 631 // Handle enums, which have an underlying type of int32, 632 // and may appear as strings. 633 // The case of an enum appearing as a number is handled 634 // at the bottom of this function. 635 if inputValue[0] == '"' && prop != nil && prop.Enum != "" { 636 vmap := proto.EnumValueMap(prop.Enum) 637 // Don't need to do unquoting; valid enum names 638 // are from a limited character set. 639 s := inputValue[1 : len(inputValue)-1] 640 n, ok := vmap[string(s)] 641 if !ok { 642 return fmt.Errorf("unknown value %q for enum %s", s, prop.Enum) 643 } 644 if target.Kind() == reflect.Ptr { // proto2 645 target.Set(reflect.New(targetType.Elem())) 646 target = target.Elem() 647 } 648 target.SetInt(int64(n)) 649 return nil 650 } 651 652 // Handle nested messages. 653 if targetType.Kind() == reflect.Struct { 654 var jsonFields map[string]json.RawMessage 655 if err := json.Unmarshal(inputValue, &jsonFields); err != nil { 656 return err 657 } 658 659 consumeField := func(prop *proto.Properties) (json.RawMessage, bool) { 660 // Be liberal in what names we accept; both orig_name and camelName are okay. 661 fieldNames := acceptedJSONFieldNames(prop) 662 663 vOrig, okOrig := jsonFields[fieldNames.orig] 664 vCamel, okCamel := jsonFields[fieldNames.camel] 665 if !okOrig && !okCamel { 666 return nil, false 667 } 668 // If, for some reason, both are present in the data, favour the camelName. 669 var raw json.RawMessage 670 if okOrig { 671 raw = vOrig 672 delete(jsonFields, fieldNames.orig) 673 } 674 if okCamel { 675 raw = vCamel 676 delete(jsonFields, fieldNames.camel) 677 } 678 return raw, true 679 } 680 681 sprops := proto.GetProperties(targetType) 682 for i := 0; i < target.NumField(); i++ { 683 ft := target.Type().Field(i) 684 if strings.HasPrefix(ft.Name, "XXX_") { 685 continue 686 } 687 688 valueForField, ok := consumeField(sprops.Prop[i]) 689 if !ok { 690 continue 691 } 692 693 if err := u.unmarshalValue(target.Field(i), valueForField, sprops.Prop[i]); err != nil { 694 return err 695 } 696 } 697 // Check for any oneof fields. 698 if len(jsonFields) > 0 { 699 for _, oop := range sprops.OneofTypes { 700 raw, ok := consumeField(oop.Prop) 701 if !ok { 702 continue 703 } 704 nv := reflect.New(oop.Type.Elem()) 705 target.Field(oop.Field).Set(nv) 706 if err := u.unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil { 707 return err 708 } 709 } 710 } 711 if !u.AllowUnknownFields && len(jsonFields) > 0 { 712 // Pick any field to be the scapegoat. 713 var f string 714 for fname := range jsonFields { 715 f = fname 716 break 717 } 718 return fmt.Errorf("unknown field %q in %v", f, targetType) 719 } 720 return nil 721 } 722 723 // Handle arrays (which aren't encoded bytes) 724 if targetType.Kind() == reflect.Slice && targetType.Elem().Kind() != reflect.Uint8 { 725 var slc []json.RawMessage 726 if err := json.Unmarshal(inputValue, &slc); err != nil { 727 return err 728 } 729 len := len(slc) 730 target.Set(reflect.MakeSlice(targetType, len, len)) 731 for i := 0; i < len; i++ { 732 if err := u.unmarshalValue(target.Index(i), slc[i], prop); err != nil { 733 return err 734 } 735 } 736 return nil 737 } 738 739 // Handle maps (whose keys are always strings) 740 if targetType.Kind() == reflect.Map { 741 var mp map[string]json.RawMessage 742 if err := json.Unmarshal(inputValue, &mp); err != nil { 743 return err 744 } 745 target.Set(reflect.MakeMap(targetType)) 746 var keyprop, valprop *proto.Properties 747 if prop != nil { 748 // These could still be nil if the protobuf metadata is broken somehow. 749 // TODO: This won't work because the fields are unexported. 750 // We should probably just reparse them. 751 //keyprop, valprop = prop.mkeyprop, prop.mvalprop 752 } 753 for ks, raw := range mp { 754 // Unmarshal map key. The core json library already decoded the key into a 755 // string, so we handle that specially. Other types were quoted post-serialization. 756 var k reflect.Value 757 if targetType.Key().Kind() == reflect.String { 758 k = reflect.ValueOf(ks) 759 } else { 760 k = reflect.New(targetType.Key()).Elem() 761 if err := u.unmarshalValue(k, json.RawMessage(ks), keyprop); err != nil { 762 return err 763 } 764 } 765 766 // Unmarshal map value. 767 v := reflect.New(targetType.Elem()).Elem() 768 if err := u.unmarshalValue(v, raw, valprop); err != nil { 769 return err 770 } 771 target.SetMapIndex(k, v) 772 } 773 return nil 774 } 775 776 // 64-bit integers can be encoded as strings. In this case we drop 777 // the quotes and proceed as normal. 778 isNum := targetType.Kind() == reflect.Int64 || targetType.Kind() == reflect.Uint64 779 if isNum && strings.HasPrefix(string(inputValue), `"`) { 780 inputValue = inputValue[1 : len(inputValue)-1] 781 } 782 783 // Use the encoding/json for parsing other value types. 784 return json.Unmarshal(inputValue, target.Addr().Interface()) 785} 786 787// jsonProperties returns parsed proto.Properties for the field and corrects JSONName attribute. 788func jsonProperties(f reflect.StructField, origName bool) *proto.Properties { 789 var prop proto.Properties 790 prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f) 791 if origName || prop.JSONName == "" { 792 prop.JSONName = prop.OrigName 793 } 794 return &prop 795} 796 797type fieldNames struct { 798 orig, camel string 799} 800 801func acceptedJSONFieldNames(prop *proto.Properties) fieldNames { 802 opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName} 803 if prop.JSONName != "" { 804 opts.camel = prop.JSONName 805 } 806 return opts 807} 808 809// Writer wrapper inspired by https://blog.golang.org/errors-are-values 810type errWriter struct { 811 writer io.Writer 812 err error 813} 814 815func (w *errWriter) write(str string) { 816 if w.err != nil { 817 return 818 } 819 _, w.err = w.writer.Write([]byte(str)) 820} 821 822// Map fields may have key types of non-float scalars, strings and enums. 823// The easiest way to sort them in some deterministic order is to use fmt. 824// If this turns out to be inefficient we can always consider other options, 825// such as doing a Schwartzian transform. 826// 827// Numeric keys are sorted in numeric order per 828// https://developers.google.com/protocol-buffers/docs/proto#maps. 829type mapKeys []reflect.Value 830 831func (s mapKeys) Len() int { return len(s) } 832func (s mapKeys) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 833func (s mapKeys) Less(i, j int) bool { 834 if k := s[i].Kind(); k == s[j].Kind() { 835 switch k { 836 case reflect.Int32, reflect.Int64: 837 return s[i].Int() < s[j].Int() 838 case reflect.Uint32, reflect.Uint64: 839 return s[i].Uint() < s[j].Uint() 840 } 841 } 842 return fmt.Sprint(s[i].Interface()) < fmt.Sprint(s[j].Interface()) 843} 844