encode.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  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(nil, m)
  94. }
  95. // MarshalAppend appends the JSON format encoding of m to b,
  96. // returning the result.
  97. func (o MarshalOptions) MarshalAppend(b []byte, m proto.Message) ([]byte, error) {
  98. return o.marshal(b, m)
  99. }
  100. // marshal is a centralized function that all marshal operations go through.
  101. // For profiling purposes, avoid changing the name of this function or
  102. // introducing other code paths for marshal that do not go through this.
  103. func (o MarshalOptions) marshal(b []byte, m proto.Message) ([]byte, error) {
  104. if o.Multiline && o.Indent == "" {
  105. o.Indent = defaultIndent
  106. }
  107. if o.Resolver == nil {
  108. o.Resolver = protoregistry.GlobalTypes
  109. }
  110. internalEnc, err := json.NewEncoder(b, o.Indent)
  111. if err != nil {
  112. return nil, err
  113. }
  114. // Treat nil message interface as an empty message,
  115. // in which case the output in an empty JSON object.
  116. if m == nil {
  117. return append(b, '{', '}'), nil
  118. }
  119. enc := encoder{internalEnc, o}
  120. if err := enc.marshalMessage(m.ProtoReflect(), ""); err != nil {
  121. return nil, err
  122. }
  123. if o.AllowPartial {
  124. return enc.Bytes(), nil
  125. }
  126. return enc.Bytes(), proto.CheckInitialized(m)
  127. }
  128. type encoder struct {
  129. *json.Encoder
  130. opts MarshalOptions
  131. }
  132. // typeFieldDesc is a synthetic field descriptor used for the "@type" field.
  133. var typeFieldDesc = func() protoreflect.FieldDescriptor {
  134. var fd filedesc.Field
  135. fd.L0.FullName = "@type"
  136. fd.L0.Index = -1
  137. fd.L1.Cardinality = protoreflect.Optional
  138. fd.L1.Kind = protoreflect.StringKind
  139. return &fd
  140. }()
  141. // typeURLFieldRanger wraps a protoreflect.Message and modifies its Range method
  142. // to additionally iterate over a synthetic field for the type URL.
  143. type typeURLFieldRanger struct {
  144. order.FieldRanger
  145. typeURL string
  146. }
  147. func (m typeURLFieldRanger) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
  148. if !f(typeFieldDesc, protoreflect.ValueOfString(m.typeURL)) {
  149. return
  150. }
  151. m.FieldRanger.Range(f)
  152. }
  153. // unpopulatedFieldRanger wraps a protoreflect.Message and modifies its Range
  154. // method to additionally iterate over unpopulated fields.
  155. type unpopulatedFieldRanger struct{ protoreflect.Message }
  156. func (m unpopulatedFieldRanger) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
  157. fds := m.Descriptor().Fields()
  158. for i := 0; i < fds.Len(); i++ {
  159. fd := fds.Get(i)
  160. if m.Has(fd) || fd.ContainingOneof() != nil {
  161. continue // ignore populated fields and fields within a oneofs
  162. }
  163. v := m.Get(fd)
  164. isProto2Scalar := fd.Syntax() == protoreflect.Proto2 && fd.Default().IsValid()
  165. isSingularMessage := fd.Cardinality() != protoreflect.Repeated && fd.Message() != nil
  166. if isProto2Scalar || isSingularMessage {
  167. v = protoreflect.Value{} // use invalid value to emit null
  168. }
  169. if !f(fd, v) {
  170. return
  171. }
  172. }
  173. m.Message.Range(f)
  174. }
  175. // marshalMessage marshals the fields in the given protoreflect.Message.
  176. // If the typeURL is non-empty, then a synthetic "@type" field is injected
  177. // containing the URL as the value.
  178. func (e encoder) marshalMessage(m protoreflect.Message, typeURL string) error {
  179. if !flags.ProtoLegacy && messageset.IsMessageSet(m.Descriptor()) {
  180. return errors.New("no support for proto1 MessageSets")
  181. }
  182. if marshal := wellKnownTypeMarshaler(m.Descriptor().FullName()); marshal != nil {
  183. return marshal(e, m)
  184. }
  185. e.StartObject()
  186. defer e.EndObject()
  187. var fields order.FieldRanger = m
  188. if e.opts.EmitUnpopulated {
  189. fields = unpopulatedFieldRanger{m}
  190. }
  191. if typeURL != "" {
  192. fields = typeURLFieldRanger{fields, typeURL}
  193. }
  194. var err error
  195. order.RangeFields(fields, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
  196. name := fd.JSONName()
  197. if e.opts.UseProtoNames {
  198. name = fd.TextName()
  199. }
  200. if err = e.WriteName(name); err != nil {
  201. return false
  202. }
  203. if err = e.marshalValue(v, fd); err != nil {
  204. return false
  205. }
  206. return true
  207. })
  208. return err
  209. }
  210. // marshalValue marshals the given protoreflect.Value.
  211. func (e encoder) marshalValue(val protoreflect.Value, fd protoreflect.FieldDescriptor) error {
  212. switch {
  213. case fd.IsList():
  214. return e.marshalList(val.List(), fd)
  215. case fd.IsMap():
  216. return e.marshalMap(val.Map(), fd)
  217. default:
  218. return e.marshalSingular(val, fd)
  219. }
  220. }
  221. // marshalSingular marshals the given non-repeated field value. This includes
  222. // all scalar types, enums, messages, and groups.
  223. func (e encoder) marshalSingular(val protoreflect.Value, fd protoreflect.FieldDescriptor) error {
  224. if !val.IsValid() {
  225. e.WriteNull()
  226. return nil
  227. }
  228. switch kind := fd.Kind(); kind {
  229. case protoreflect.BoolKind:
  230. e.WriteBool(val.Bool())
  231. case protoreflect.StringKind:
  232. if e.WriteString(val.String()) != nil {
  233. return errors.InvalidUTF8(string(fd.FullName()))
  234. }
  235. case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
  236. e.WriteInt(val.Int())
  237. case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
  238. e.WriteUint(val.Uint())
  239. case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Uint64Kind,
  240. protoreflect.Sfixed64Kind, protoreflect.Fixed64Kind:
  241. // 64-bit integers are written out as JSON string.
  242. e.WriteString(val.String())
  243. case protoreflect.FloatKind:
  244. // Encoder.WriteFloat handles the special numbers NaN and infinites.
  245. e.WriteFloat(val.Float(), 32)
  246. case protoreflect.DoubleKind:
  247. // Encoder.WriteFloat handles the special numbers NaN and infinites.
  248. e.WriteFloat(val.Float(), 64)
  249. case protoreflect.BytesKind:
  250. e.WriteString(base64.StdEncoding.EncodeToString(val.Bytes()))
  251. case protoreflect.EnumKind:
  252. if fd.Enum().FullName() == genid.NullValue_enum_fullname {
  253. e.WriteNull()
  254. } else {
  255. desc := fd.Enum().Values().ByNumber(val.Enum())
  256. if e.opts.UseEnumNumbers || desc == nil {
  257. e.WriteInt(int64(val.Enum()))
  258. } else {
  259. e.WriteString(string(desc.Name()))
  260. }
  261. }
  262. case protoreflect.MessageKind, protoreflect.GroupKind:
  263. if err := e.marshalMessage(val.Message(), ""); err != nil {
  264. return err
  265. }
  266. default:
  267. panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind))
  268. }
  269. return nil
  270. }
  271. // marshalList marshals the given protoreflect.List.
  272. func (e encoder) marshalList(list protoreflect.List, fd protoreflect.FieldDescriptor) error {
  273. e.StartArray()
  274. defer e.EndArray()
  275. for i := 0; i < list.Len(); i++ {
  276. item := list.Get(i)
  277. if err := e.marshalSingular(item, fd); err != nil {
  278. return err
  279. }
  280. }
  281. return nil
  282. }
  283. // marshalMap marshals given protoreflect.Map.
  284. func (e encoder) marshalMap(mmap protoreflect.Map, fd protoreflect.FieldDescriptor) error {
  285. e.StartObject()
  286. defer e.EndObject()
  287. var err error
  288. order.RangeEntries(mmap, order.GenericKeyOrder, func(k protoreflect.MapKey, v protoreflect.Value) bool {
  289. if err = e.WriteName(k.String()); err != nil {
  290. return false
  291. }
  292. if err = e.marshalSingular(v, fd.MapValue()); err != nil {
  293. return false
  294. }
  295. return true
  296. })
  297. return err
  298. }