// jsonProperties returns parsed proto.Properties for the field and corrects JSONName attribute. func jsonProperties(f reflect.StructField, origName bool) *proto.Properties { var prop proto.Properties prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f) if origName || prop.JSONName == "" { prop.JSONName = prop.OrigName } return &prop }
func acceptedJSONFieldNames(f reflect.StructField) fieldNames { var prop proto.Properties prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f) opts := fieldNames{orig: prop.OrigName, camel: prop.OrigName} if prop.JSONName != "" { opts.camel = prop.JSONName } return opts }
// marshalObject writes a struct to the Writer. func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent string) error { out.write("{") if m.Indent != "" { out.write("\n") } s := reflect.ValueOf(v).Elem() writeBeforeField := "" for i := 0; i < s.NumField(); i++ { value := s.Field(i) valueField := s.Type().Field(i) if strings.HasPrefix(valueField.Name, "XXX_") { continue } fieldName := jsonFieldName(valueField) // TODO: proto3 objects should have default values omitted. // IsNil will panic on most value kinds. switch value.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: if value.IsNil() { continue } } // Oneof fields need special handling. if valueField.Tag.Get("protobuf_oneof") != "" { // value is an interface containing &T{real_value}. sv := value.Elem().Elem() // interface -> *T -> T value = sv.Field(0) valueField = sv.Type().Field(0) var p proto.Properties p.Parse(sv.Type().Field(0).Tag.Get("protobuf")) fieldName = p.OrigName } out.write(writeBeforeField) if m.Indent != "" { out.write(indent) out.write(m.Indent) } out.write(`"`) out.write(fieldName) out.write(`":`) if m.Indent != "" { out.write(" ") } if err := m.marshalValue(out, value, valueField, indent); err != nil { return err } if m.Indent != "" { writeBeforeField = ",\n" } else { writeBeforeField = "," } } if m.Indent != "" { out.write("\n") out.write(indent) } out.write("}") return out.err }
// jsonFieldName returns the field name to use. func jsonFieldName(f reflect.StructField) string { var prop proto.Properties prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f) return prop.OrigName }
// marshalObject writes a struct to the Writer. func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent string) error { s := reflect.ValueOf(v).Elem() // Handle well-known types. type wkt interface { XXX_WellKnownType() string } if wkt, ok := v.(wkt); ok { switch wkt.XXX_WellKnownType() { case "DoubleValue", "FloatValue", "Int64Value", "UInt64Value", "Int32Value", "UInt32Value", "BoolValue", "StringValue", "BytesValue": // "Wrappers use the same representation in JSON // as the wrapped primitive type, ..." sprop := proto.GetProperties(s.Type()) return m.marshalValue(out, sprop.Prop[0], s.Field(0), indent) case "Duration": // "Generated output always contains 3, 6, or 9 fractional digits, // depending on required precision." s, ns := s.Field(0).Int(), s.Field(1).Int() d := time.Duration(s)*time.Second + time.Duration(ns)*time.Nanosecond x := fmt.Sprintf("%.9f", d.Seconds()) x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") out.write(`"`) out.write(x) out.write(`s"`) return out.err case "Timestamp": // "RFC 3339, where generated output will always be Z-normalized // and uses 3, 6 or 9 fractional digits." s, ns := s.Field(0).Int(), s.Field(1).Int() t := time.Unix(s, ns).UTC() // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits). x := t.Format("2006-01-02T15:04:05.000000000") x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") out.write(`"`) out.write(x) out.write(`Z"`) return out.err } } out.write("{") if m.Indent != "" { out.write("\n") } firstField := true for i := 0; i < s.NumField(); i++ { value := s.Field(i) valueField := s.Type().Field(i) if strings.HasPrefix(valueField.Name, "XXX_") { continue } // IsNil will panic on most value kinds. switch value.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: if value.IsNil() { continue } } if !m.EmitDefaults { switch value.Kind() { case reflect.Bool: if !value.Bool() { continue } case reflect.Int32, reflect.Int64: if value.Int() == 0 { continue } case reflect.Uint32, reflect.Uint64: if value.Uint() == 0 { continue } case reflect.Float32, reflect.Float64: if value.Float() == 0 { continue } case reflect.String: if value.Len() == 0 { continue } } } // Oneof fields need special handling. if valueField.Tag.Get("protobuf_oneof") != "" { // value is an interface containing &T{real_value}. sv := value.Elem().Elem() // interface -> *T -> T value = sv.Field(0) valueField = sv.Type().Field(0) } prop := jsonProperties(valueField, m.OrigName) if !firstField { m.writeSep(out) } if err := m.marshalField(out, prop, value, indent); err != nil { return err } firstField = false } // Handle proto2 extensions. if ep, ok := v.(extendableProto); ok { extensions := proto.RegisteredExtensions(v) extensionMap := ep.ExtensionMap() // Sort extensions for stable output. ids := make([]int32, 0, len(extensionMap)) for id := range extensionMap { ids = append(ids, id) } sort.Sort(int32Slice(ids)) for _, id := range ids { desc := extensions[id] if desc == nil { // unknown extension continue } ext, extErr := proto.GetExtension(ep, desc) if extErr != nil { return extErr } value := reflect.ValueOf(ext) var prop proto.Properties prop.Parse(desc.Tag) prop.JSONName = fmt.Sprintf("[%s]", desc.Name) if !firstField { m.writeSep(out) } if err := m.marshalField(out, &prop, value, indent); err != nil { return err } firstField = false } } if m.Indent != "" { out.write("\n") out.write(indent) } out.write("}") return out.err }
// marshalObject writes a struct to the Writer. func (m *Marshaler) marshalObject(out *errWriter, v proto.Message, indent string) error { out.write("{") if m.Indent != "" { out.write("\n") } s := reflect.ValueOf(v).Elem() firstField := true for i := 0; i < s.NumField(); i++ { value := s.Field(i) valueField := s.Type().Field(i) if strings.HasPrefix(valueField.Name, "XXX_") { continue } // TODO: proto3 objects should have default values omitted. // IsNil will panic on most value kinds. switch value.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice: if value.IsNil() { continue } } // Oneof fields need special handling. if valueField.Tag.Get("protobuf_oneof") != "" { // value is an interface containing &T{real_value}. sv := value.Elem().Elem() // interface -> *T -> T value = sv.Field(0) valueField = sv.Type().Field(0) } prop := jsonProperties(valueField) if !firstField { m.writeSep(out) } if err := m.marshalField(out, prop, value, indent); err != nil { return err } firstField = false } // Handle proto2 extensions. if ep, ok := v.(extendableProto); ok { extensions := proto.RegisteredExtensions(v) extensionMap := ep.ExtensionMap() // Sort extensions for stable output. ids := make([]int32, 0, len(extensionMap)) for id := range extensionMap { ids = append(ids, id) } sort.Sort(int32Slice(ids)) for _, id := range ids { desc := extensions[id] if desc == nil { // unknown extension continue } ext, extErr := proto.GetExtension(ep, desc) if extErr != nil { return extErr } value := reflect.ValueOf(ext) var prop proto.Properties prop.Parse(desc.Tag) prop.OrigName = fmt.Sprintf("[%s]", desc.Name) if !firstField { m.writeSep(out) } if err := m.marshalField(out, &prop, value, indent); err != nil { return err } firstField = false } } if m.Indent != "" { out.write("\n") out.write(indent) } out.write("}") return out.err }
// jsonProperties returns parsed proto.Properties for the field. func jsonProperties(f reflect.StructField) *proto.Properties { var prop proto.Properties prop.Init(f.Type, f.Name, f.Tag.Get("protobuf"), &f) return &prop }
// unmarshalValue converts/copies a value into the target. func unmarshalValue(target reflect.Value, inputValue json.RawMessage) error { targetType := target.Type() // Allocate memory for pointer fields. if targetType.Kind() == reflect.Ptr { target.Set(reflect.New(targetType.Elem())) return unmarshalValue(target.Elem(), inputValue) } // Handle nested messages. if targetType.Kind() == reflect.Struct { var jsonFields map[string]json.RawMessage if err := json.Unmarshal(inputValue, &jsonFields); err != nil { return err } for i := 0; i < target.NumField(); i++ { ft := target.Type().Field(i) if strings.HasPrefix(ft.Name, "XXX_") { continue } fieldName := jsonFieldName(ft) if valueForField, ok := jsonFields[fieldName]; ok { if err := unmarshalValue(target.Field(i), valueForField); err != nil { return err } delete(jsonFields, fieldName) } } // Check for any oneof fields. // This might be slow; we can optimise it if it becomes a problem. type oneofMessage interface { XXX_OneofFuncs() (func(proto.Message, *proto.Buffer) error, func(proto.Message, int, int, *proto.Buffer) (bool, error), []interface{}) } var oneofTypes []interface{} if om, ok := reflect.Zero(reflect.PtrTo(targetType)).Interface().(oneofMessage); ok { _, _, oneofTypes = om.XXX_OneofFuncs() } for fname, raw := range jsonFields { for _, oot := range oneofTypes { sp := reflect.ValueOf(oot).Type() // *T var props proto.Properties props.Parse(sp.Elem().Field(0).Tag.Get("protobuf")) if props.OrigName != fname { continue } nv := reflect.New(sp.Elem()) // There will be exactly one interface field that // this new value is assignable to. for i := 0; i < targetType.NumField(); i++ { f := targetType.Field(i) if f.Type.Kind() != reflect.Interface { continue } if !nv.Type().AssignableTo(f.Type) { continue } target.Field(i).Set(nv) break } if err := unmarshalValue(nv.Elem().Field(0), raw); err != nil { return err } delete(jsonFields, fname) break } } if len(jsonFields) > 0 { // Pick any field to be the scapegoat. var f string for fname := range jsonFields { f = fname break } return fmt.Errorf("unknown field %q in %v", f, targetType) } return nil } // Handle arrays (which aren't encoded bytes) if targetType != byteArrayType && targetType.Kind() == reflect.Slice { var slc []json.RawMessage if err := json.Unmarshal(inputValue, &slc); err != nil { return err } len := len(slc) target.Set(reflect.MakeSlice(targetType, len, len)) for i := 0; i < len; i++ { if err := unmarshalValue(target.Index(i), slc[i]); err != nil { return err } } return nil } // Handle maps (whose keys are always strings) if targetType.Kind() == reflect.Map { var mp map[string]json.RawMessage if err := json.Unmarshal(inputValue, &mp); err != nil { return err } target.Set(reflect.MakeMap(targetType)) for ks, raw := range mp { // Unmarshal map key. The core json library already decoded the key into a // string, so we handle that specially. Other types were quoted post-serialization. var k reflect.Value if targetType.Key().Kind() == reflect.String { k = reflect.ValueOf(ks) } else { k = reflect.New(targetType.Key()).Elem() if err := unmarshalValue(k, json.RawMessage(ks)); err != nil { return err } } // Unmarshal map value. v := reflect.New(targetType.Elem()).Elem() if err := unmarshalValue(v, raw); err != nil { return err } target.SetMapIndex(k, v) } return nil } // 64-bit integers can be encoded as strings. In this case we drop // the quotes and proceed as normal. isNum := targetType.Kind() == reflect.Int64 || targetType.Kind() == reflect.Uint64 if isNum && strings.HasPrefix(string(inputValue), `"`) { inputValue = inputValue[1 : len(inputValue)-1] } // Use the encoding/json for parsing other value types. return json.Unmarshal(inputValue, target.Addr().Interface()) }