encode.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. package protojson
  5. import (
  6. "encoding/base64"
  7. "fmt"
  8. "google.golang.org/protobuf/internal/encoding/json"
  9. "google.golang.org/protobuf/internal/encoding/messageset"
  10. "google.golang.org/protobuf/internal/errors"
  11. "google.golang.org/protobuf/internal/filedesc"
  12. "google.golang.org/protobuf/internal/flags"
  13. "google.golang.org/protobuf/internal/genid"
  14. "google.golang.org/protobuf/internal/order"
  15. "google.golang.org/protobuf/internal/pragma"
  16. "google.golang.org/protobuf/proto"
  17. "google.golang.org/protobuf/reflect/protoreflect"
  18. "google.golang.org/protobuf/reflect/protoregistry"
  19. )
  20. const defaultIndent = " "
  21. // Format formats the message as a multiline string.
  22. // This function is only intended for human consumption and ignores errors.
  23. // Do not depend on the output being stable. It may change over time across
  24. // different versions of the program.
  25. func Format(m proto.Message) string {
  26. return MarshalOptions{Multiline: true}.Format(m)
  27. }
  28. // Marshal writes the given proto.Message in JSON format using default options.
  29. // Do not depend on the output being stable. It may change over time across
  30. // different versions of the program.
  31. func Marshal(m proto.Message) ([]byte, error) {
  32. return MarshalOptions{}.Marshal(m)
  33. }
  34. // MarshalOptions is a configurable JSON format marshaler.
  35. type MarshalOptions struct {
  36. pragma.NoUnkeyedLiterals
  37. // Multiline specifies whether the marshaler should format the output in
  38. // indented-form with every textual element on a new line.
  39. // If Indent is an empty string, then an arbitrary indent is chosen.
  40. Multiline bool
  41. // Indent specifies the set of indentation characters to use in a multiline
  42. // formatted output such that every entry is preceded by Indent and
  43. // terminated by a newline. If non-empty, then Multiline is treated as true.
  44. // Indent can only be composed of space or tab characters.
  45. Indent string
  46. // AllowPartial allows messages that have missing required fields to marshal
  47. // without returning an error. If AllowPartial is false (the default),
  48. // Marshal will return error if there are any missing required fields.
  49. AllowPartial bool
  50. // UseProtoNames uses proto field name instead of lowerCamelCase name in JSON
  51. // field names.
  52. UseProtoNames bool
  53. // UseEnumNumbers emits enum values as numbers.
  54. UseEnumNumbers bool
  55. // EmitUnpopulated specifies whether to emit unpopulated fields. It does not
  56. // emit unpopulated oneof fields or unpopulated extension fields.
  57. // The JSON value emitted for unpopulated fields are as follows:
  58. // ╔═══════╤════════════════════════════╗
  59. // ║ JSON │ Protobuf field ║
  60. // ╠═══════╪════════════════════════════╣
  61. // ║ false │ proto3 boolean fields ║
  62. // ║ 0 │ proto3 numeric fields ║
  63. // ║ "" │ proto3 string/bytes fields ║
  64. // ║ null │ proto2 scalar fields ║
  65. // ║ null │ message fields ║
  66. // ║ [] │ list fields ║
  67. // ║ {} │ map fields ║
  68. // ╚═══════╧════════════════════════════╝
  69. EmitUnpopulated bool
  70. // Resolver is used for looking up types when expanding google.protobuf.Any
  71. // messages. If nil, this defaults to using protoregistry.GlobalTypes.
  72. Resolver interface {
  73. protoregistry.ExtensionTypeResolver
  74. protoregistry.MessageTypeResolver
  75. }
  76. }
  77. // Format formats the message as a string.
  78. // This method is only intended for human consumption and ignores errors.
  79. // Do not depend on the output being stable. It may change over time across
  80. // different versions of the program.
  81. func (o MarshalOptions) Format(m proto.Message) string {
  82. if m == nil || !m.ProtoReflect().IsValid() {
  83. return "<nil>" // invalid syntax, but okay since this is for debugging
  84. }
  85. o.AllowPartial = true
  86. b, _ := o.Marshal(m)
  87. return string(b)
  88. }
  89. // Marshal marshals the given proto.Message in the JSON format using options in
  90. // MarshalOptions. Do not depend on the output being stable. It may change over
  91. // time across different versions of the program.
  92. func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) {
  93. return o.marshal(m)
  94. }
  95. // marshal is a centralized function that all marshal operations go through.
  96. // For profiling purposes, avoid changing the name of this function or
  97. // introducing other code paths for marshal that do not go through this.
  98. func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) {
  99. if o.Multiline && o.Indent == "" {
  100. o.Indent = defaultIndent
  101. }
  102. if o.Resolver == nil {
  103. o.Resolver = protoregistry.GlobalTypes
  104. }
  105. internalEnc, err := json.NewEncoder(o.Indent)
  106. if err != nil {
  107. return nil, err
  108. }
  109. // Treat nil message interface as an empty message,
  110. // in which case the output in an empty JSON object.
  111. if m == nil {
  112. return []byte("{}"), nil
  113. }
  114. enc := encoder{internalEnc, o}
  115. if err := enc.marshalMessage(m.ProtoReflect(), ""); err != nil {
  116. return nil, err
  117. }
  118. if o.AllowPartial {
  119. return enc.Bytes(), nil
  120. }
  121. return enc.Bytes(), proto.CheckInitialized(m)
  122. }
  123. type encoder struct {
  124. *json.Encoder
  125. opts MarshalOptions
  126. }
  127. // typeFieldDesc is a synthetic field descriptor used for the "@type" field.
  128. var typeFieldDesc = func() protoreflect.FieldDescriptor {
  129. var fd filedesc.Field
  130. fd.L0.FullName = "@type"
  131. fd.L0.Index = -1
  132. fd.L1.Cardinality = protoreflect.Optional
  133. fd.L1.Kind = protoreflect.StringKind
  134. return &fd
  135. }()
  136. // typeURLFieldRanger wraps a protoreflect.Message and modifies its Range method
  137. // to additionally iterate over a synthetic field for the type URL.
  138. type typeURLFieldRanger struct {
  139. order.FieldRanger
  140. typeURL string
  141. }
  142. func (m typeURLFieldRanger) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
  143. if !f(typeFieldDesc, protoreflect.ValueOfString(m.typeURL)) {
  144. return
  145. }
  146. m.FieldRanger.Range(f)
  147. }
  148. // unpopulatedFieldRanger wraps a protoreflect.Message and modifies its Range
  149. // method to additionally iterate over unpopulated fields.
  150. type unpopulatedFieldRanger struct{ protoreflect.Message }
  151. func (m unpopulatedFieldRanger) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
  152. fds := m.Descriptor().Fields()
  153. for i := 0; i < fds.Len(); i++ {
  154. fd := fds.Get(i)
  155. if m.Has(fd) || fd.ContainingOneof() != nil {
  156. continue // ignore populated fields and fields within a oneofs
  157. }
  158. v := m.Get(fd)
  159. isProto2Scalar := fd.Syntax() == protoreflect.Proto2 && fd.Default().IsValid()
  160. isSingularMessage := fd.Cardinality() != protoreflect.Repeated && fd.Message() != nil
  161. if isProto2Scalar || isSingularMessage {
  162. v = protoreflect.Value{} // use invalid value to emit null
  163. }
  164. if !f(fd, v) {
  165. return
  166. }
  167. }
  168. m.Message.Range(f)
  169. }
  170. // marshalMessage marshals the fields in the given protoreflect.Message.
  171. // If the typeURL is non-empty, then a synthetic "@type" field is injected
  172. // containing the URL as the value.
  173. func (e encoder) marshalMessage(m protoreflect.Message, typeURL string) error {
  174. if !flags.ProtoLegacy && messageset.IsMessageSet(m.Descriptor()) {
  175. return errors.New("no support for proto1 MessageSets")
  176. }
  177. if marshal := wellKnownTypeMarshaler(m.Descriptor().FullName()); marshal != nil {
  178. return marshal(e, m)
  179. }
  180. e.StartObject()
  181. defer e.EndObject()
  182. var fields order.FieldRanger = m
  183. if e.opts.EmitUnpopulated {
  184. fields = unpopulatedFieldRanger{m}
  185. }
  186. if typeURL != "" {
  187. fields = typeURLFieldRanger{fields, typeURL}
  188. }
  189. var err error
  190. order.RangeFields(fields, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
  191. name := fd.JSONName()
  192. if e.opts.UseProtoNames {
  193. name = fd.TextName()
  194. }
  195. if err = e.WriteName(name); err != nil {
  196. return false
  197. }
  198. if err = e.marshalValue(v, fd); err != nil {
  199. return false
  200. }
  201. return true
  202. })
  203. return err
  204. }
  205. // marshalValue marshals the given protoreflect.Value.
  206. func (e encoder) marshalValue(val protoreflect.Value, fd protoreflect.FieldDescriptor) error {
  207. switch {
  208. case fd.IsList():
  209. return e.marshalList(val.List(), fd)
  210. case fd.IsMap():
  211. return e.marshalMap(val.Map(), fd)
  212. default:
  213. return e.marshalSingular(val, fd)
  214. }
  215. }
  216. // marshalSingular marshals the given non-repeated field value. This includes
  217. // all scalar types, enums, messages, and groups.
  218. func (e encoder) marshalSingular(val protoreflect.Value, fd protoreflect.FieldDescriptor) error {
  219. if !val.IsValid() {
  220. e.WriteNull()
  221. return nil
  222. }
  223. switch kind := fd.Kind(); kind {
  224. case protoreflect.BoolKind:
  225. e.WriteBool(val.Bool())
  226. case protoreflect.StringKind:
  227. if e.WriteString(val.String()) != nil {
  228. return errors.InvalidUTF8(string(fd.FullName()))
  229. }
  230. case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
  231. e.WriteInt(val.Int())
  232. case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
  233. e.WriteUint(val.Uint())
  234. case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Uint64Kind,
  235. protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind:
  236. // 64-bit integers are written out as JSON string.
  237. e.WriteString(val.String())
  238. case protoreflect.FloatKind:
  239. // Encoder.WriteFloat handles the special numbers NaN and infinites.
  240. e.WriteFloat(val.Float(), 32)
  241. case protoreflect.DoubleKind:
  242. // Encoder.WriteFloat handles the special numbers NaN and infinites.
  243. e.WriteFloat(val.Float(), 64)
  244. case protoreflect.BytesKind:
  245. e.WriteString(base64.StdEncoding.EncodeToString(val.Bytes()))
  246. case protoreflect.EnumKind:
  247. if fd.Enum().FullName() == genid.NullValue_enum_fullname {
  248. e.WriteNull()
  249. } else {
  250. desc := fd.Enum().Values().ByNumber(val.Enum())
  251. if e.opts.UseEnumNumbers || desc == nil {
  252. e.WriteInt(int64(val.Enum()))
  253. } else {
  254. e.WriteString(string(desc.Name()))
  255. }
  256. }
  257. case protoreflect.MessageKind, protoreflect.GroupKind:
  258. if err := e.marshalMessage(val.Message(), ""); err != nil {
  259. return err
  260. }
  261. default:
  262. panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind))
  263. }
  264. return nil
  265. }
  266. // marshalList marshals the given protoreflect.List.
  267. func (e encoder) marshalList(list protoreflect.List, fd protoreflect.FieldDescriptor) error {
  268. e.StartArray()
  269. defer e.EndArray()
  270. for i := 0; i < list.Len(); i++ {
  271. item := list.Get(i)
  272. if err := e.marshalSingular(item, fd); err != nil {
  273. return err
  274. }
  275. }
  276. return nil
  277. }
  278. // marshalMap marshals given protoreflect.Map.
  279. func (e encoder) marshalMap(mmap protoreflect.Map, fd protoreflect.FieldDescriptor) error {
  280. e.StartObject()
  281. defer e.EndObject()
  282. var err error
  283. order.RangeEntries(mmap, order.GenericKeyOrder, func(k protoreflect.MapKey, v protoreflect.Value) bool {
  284. if err = e.WriteName(k.String()); err != nil {
  285. return false
  286. }
  287. if err = e.marshalSingular(v, fd.MapValue()); err != nil {
  288. return false
  289. }
  290. return true
  291. })
  292. return err
  293. }