encode.go 13 KB

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