encode.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. // Copyright 2015 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 jsonpb
  5. import (
  6. "encoding/json"
  7. "errors"
  8. "fmt"
  9. "io"
  10. "math"
  11. "reflect"
  12. "sort"
  13. "strconv"
  14. "strings"
  15. "time"
  16. "github.com/golang/protobuf/proto"
  17. "google.golang.org/protobuf/encoding/protojson"
  18. protoV2 "google.golang.org/protobuf/proto"
  19. "google.golang.org/protobuf/reflect/protoreflect"
  20. "google.golang.org/protobuf/reflect/protoregistry"
  21. )
  22. const wrapJSONMarshalV2 = false
  23. // Marshaler is a configurable object for marshaling protocol buffer messages
  24. // to the specified JSON representation.
  25. type Marshaler struct {
  26. // OrigName specifies whether to use the original protobuf name for fields.
  27. OrigName bool
  28. // EnumsAsInts specifies whether to render enum values as integers,
  29. // as opposed to string values.
  30. EnumsAsInts bool
  31. // EmitDefaults specifies whether to render fields with zero values.
  32. EmitDefaults bool
  33. // Indent controls whether the output is compact or not.
  34. // If empty, the output is compact JSON. Otherwise, every JSON object
  35. // entry and JSON array value will be on its own line.
  36. // Each line will be preceded by repeated copies of Indent, where the
  37. // number of copies is the current indentation depth.
  38. Indent string
  39. // AnyResolver is used to resolve the google.protobuf.Any well-known type.
  40. // If unset, the global registry is used by default.
  41. AnyResolver AnyResolver
  42. }
  43. // JSONPBMarshaler is implemented by protobuf messages that customize the
  44. // way they are marshaled to JSON. Messages that implement this should also
  45. // implement JSONPBUnmarshaler so that the custom format can be parsed.
  46. //
  47. // The JSON marshaling must follow the proto to JSON specification:
  48. // https://developers.google.com/protocol-buffers/docs/proto3#json
  49. //
  50. // Deprecated: Custom types should implement protobuf reflection instead.
  51. type JSONPBMarshaler interface {
  52. MarshalJSONPB(*Marshaler) ([]byte, error)
  53. }
  54. // Marshal serializes a protobuf message as JSON into w.
  55. func (jm *Marshaler) Marshal(w io.Writer, m proto.Message) error {
  56. b, err := jm.marshal(m)
  57. if len(b) > 0 {
  58. if _, err := w.Write(b); err != nil {
  59. return err
  60. }
  61. }
  62. return err
  63. }
  64. // MarshalToString serializes a protobuf message as JSON in string form.
  65. func (jm *Marshaler) MarshalToString(m proto.Message) (string, error) {
  66. b, err := jm.marshal(m)
  67. if err != nil {
  68. return "", err
  69. }
  70. return string(b), nil
  71. }
  72. func (jm *Marshaler) marshal(m proto.Message) ([]byte, error) {
  73. v := reflect.ValueOf(m)
  74. if m == nil || (v.Kind() == reflect.Ptr && v.IsNil()) {
  75. return nil, errors.New("Marshal called with nil")
  76. }
  77. // Check for custom marshalers first since they may not properly
  78. // implement protobuf reflection that the logic below relies on.
  79. if jsm, ok := m.(JSONPBMarshaler); ok {
  80. return jsm.MarshalJSONPB(jm)
  81. }
  82. if wrapJSONMarshalV2 {
  83. opts := protojson.MarshalOptions{
  84. UseProtoNames: jm.OrigName,
  85. UseEnumNumbers: jm.EnumsAsInts,
  86. EmitUnpopulated: jm.EmitDefaults,
  87. Indent: jm.Indent,
  88. }
  89. if jm.AnyResolver != nil {
  90. opts.Resolver = anyResolver{jm.AnyResolver}
  91. }
  92. return opts.Marshal(proto.MessageReflect(m).Interface())
  93. } else {
  94. // Check for unpopulated required fields first.
  95. m2 := proto.MessageReflect(m)
  96. if err := protoV2.CheckInitialized(m2.Interface()); err != nil {
  97. return nil, err
  98. }
  99. w := jsonWriter{Marshaler: jm}
  100. err := w.marshalMessage(m2, "", "")
  101. return w.buf, err
  102. }
  103. }
  104. type jsonWriter struct {
  105. *Marshaler
  106. buf []byte
  107. }
  108. func (w *jsonWriter) write(s string) {
  109. w.buf = append(w.buf, s...)
  110. }
  111. func (w *jsonWriter) marshalMessage(m protoreflect.Message, indent, typeURL string) error {
  112. if jsm, ok := proto.MessageV1(m.Interface()).(JSONPBMarshaler); ok {
  113. b, err := jsm.MarshalJSONPB(w.Marshaler)
  114. if err != nil {
  115. return err
  116. }
  117. if typeURL != "" {
  118. // we are marshaling this object to an Any type
  119. var js map[string]*json.RawMessage
  120. if err = json.Unmarshal(b, &js); err != nil {
  121. return fmt.Errorf("type %T produced invalid JSON: %v", m.Interface(), err)
  122. }
  123. turl, err := json.Marshal(typeURL)
  124. if err != nil {
  125. return fmt.Errorf("failed to marshal type URL %q to JSON: %v", typeURL, err)
  126. }
  127. js["@type"] = (*json.RawMessage)(&turl)
  128. if b, err = json.Marshal(js); err != nil {
  129. return err
  130. }
  131. }
  132. w.write(string(b))
  133. return nil
  134. }
  135. md := m.Descriptor()
  136. fds := md.Fields()
  137. // Handle well-known types.
  138. const secondInNanos = int64(time.Second / time.Nanosecond)
  139. switch wellKnownType(md.FullName()) {
  140. case "Any":
  141. return w.marshalAny(m, indent)
  142. case "BoolValue", "BytesValue", "StringValue",
  143. "Int32Value", "UInt32Value", "FloatValue",
  144. "Int64Value", "UInt64Value", "DoubleValue":
  145. fd := fds.ByNumber(1)
  146. return w.marshalValue(fd, m.Get(fd), indent)
  147. case "Duration":
  148. const maxSecondsInDuration = 315576000000
  149. // "Generated output always contains 0, 3, 6, or 9 fractional digits,
  150. // depending on required precision."
  151. s := m.Get(fds.ByNumber(1)).Int()
  152. ns := m.Get(fds.ByNumber(2)).Int()
  153. if s < -maxSecondsInDuration || s > maxSecondsInDuration {
  154. return fmt.Errorf("seconds out of range %v", s)
  155. }
  156. if ns <= -secondInNanos || ns >= secondInNanos {
  157. return fmt.Errorf("ns out of range (%v, %v)", -secondInNanos, secondInNanos)
  158. }
  159. if (s > 0 && ns < 0) || (s < 0 && ns > 0) {
  160. return errors.New("signs of seconds and nanos do not match")
  161. }
  162. var sign string
  163. if s < 0 || ns < 0 {
  164. sign, s, ns = "-", -1*s, -1*ns
  165. }
  166. x := fmt.Sprintf("%s%d.%09d", sign, s, ns)
  167. x = strings.TrimSuffix(x, "000")
  168. x = strings.TrimSuffix(x, "000")
  169. x = strings.TrimSuffix(x, ".000")
  170. w.write(fmt.Sprintf(`"%vs"`, x))
  171. return nil
  172. case "Timestamp":
  173. // "RFC 3339, where generated output will always be Z-normalized
  174. // and uses 0, 3, 6 or 9 fractional digits."
  175. s := m.Get(fds.ByNumber(1)).Int()
  176. ns := m.Get(fds.ByNumber(2)).Int()
  177. if ns < 0 || ns >= secondInNanos {
  178. return fmt.Errorf("ns out of range [0, %v)", secondInNanos)
  179. }
  180. t := time.Unix(s, ns).UTC()
  181. // time.RFC3339Nano isn't exactly right (we need to get 3/6/9 fractional digits).
  182. x := t.Format("2006-01-02T15:04:05.000000000")
  183. x = strings.TrimSuffix(x, "000")
  184. x = strings.TrimSuffix(x, "000")
  185. x = strings.TrimSuffix(x, ".000")
  186. w.write(fmt.Sprintf(`"%vZ"`, x))
  187. return nil
  188. case "Value":
  189. // JSON value; which is a null, number, string, bool, object, or array.
  190. od := md.Oneofs().Get(0)
  191. fd := m.WhichOneof(od)
  192. if fd == nil {
  193. return errors.New("nil Value")
  194. }
  195. return w.marshalValue(fd, m.Get(fd), indent)
  196. case "Struct", "ListValue":
  197. // JSON object or array.
  198. fd := fds.ByNumber(1)
  199. return w.marshalValue(fd, m.Get(fd), indent)
  200. }
  201. w.write("{")
  202. if w.Indent != "" {
  203. w.write("\n")
  204. }
  205. firstField := true
  206. if typeURL != "" {
  207. if err := w.marshalTypeURL(indent, typeURL); err != nil {
  208. return err
  209. }
  210. firstField = false
  211. }
  212. for i := 0; i < fds.Len(); {
  213. fd := fds.Get(i)
  214. if od := fd.ContainingOneof(); od != nil {
  215. fd = m.WhichOneof(od)
  216. i += od.Fields().Len()
  217. if fd == nil {
  218. continue
  219. }
  220. } else {
  221. i++
  222. }
  223. v := m.Get(fd)
  224. if !m.Has(fd) {
  225. if !w.EmitDefaults || fd.ContainingOneof() != nil {
  226. continue
  227. }
  228. if fd.Cardinality() != protoreflect.Repeated && (fd.Message() != nil || fd.Syntax() == protoreflect.Proto2) {
  229. v = protoreflect.Value{} // use "null" for singular messages or proto2 scalars
  230. }
  231. }
  232. if !firstField {
  233. w.writeComma()
  234. }
  235. if err := w.marshalField(fd, v, indent); err != nil {
  236. return err
  237. }
  238. firstField = false
  239. }
  240. // Handle proto2 extensions.
  241. if md.ExtensionRanges().Len() > 0 {
  242. // Collect a sorted list of all extension descriptor and values.
  243. type ext struct {
  244. desc protoreflect.FieldDescriptor
  245. val protoreflect.Value
  246. }
  247. var exts []ext
  248. m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
  249. if fd.IsExtension() {
  250. exts = append(exts, ext{fd, v})
  251. }
  252. return true
  253. })
  254. sort.Slice(exts, func(i, j int) bool {
  255. return exts[i].desc.Number() < exts[j].desc.Number()
  256. })
  257. for _, ext := range exts {
  258. if !firstField {
  259. w.writeComma()
  260. }
  261. if err := w.marshalField(ext.desc, ext.val, indent); err != nil {
  262. return err
  263. }
  264. firstField = false
  265. }
  266. }
  267. if w.Indent != "" {
  268. w.write("\n")
  269. w.write(indent)
  270. }
  271. w.write("}")
  272. return nil
  273. }
  274. func (w *jsonWriter) writeComma() {
  275. if w.Indent != "" {
  276. w.write(",\n")
  277. } else {
  278. w.write(",")
  279. }
  280. }
  281. func (w *jsonWriter) marshalAny(m protoreflect.Message, indent string) error {
  282. // "If the Any contains a value that has a special JSON mapping,
  283. // it will be converted as follows: {"@type": xxx, "value": yyy}.
  284. // Otherwise, the value will be converted into a JSON object,
  285. // and the "@type" field will be inserted to indicate the actual data type."
  286. md := m.Descriptor()
  287. typeURL := m.Get(md.Fields().ByNumber(1)).String()
  288. rawVal := m.Get(md.Fields().ByNumber(2)).Bytes()
  289. var m2 protoreflect.Message
  290. if w.AnyResolver != nil {
  291. mi, err := w.AnyResolver.Resolve(typeURL)
  292. if err != nil {
  293. return err
  294. }
  295. m2 = proto.MessageReflect(mi)
  296. } else {
  297. mt, err := protoregistry.GlobalTypes.FindMessageByURL(typeURL)
  298. if err != nil {
  299. return err
  300. }
  301. m2 = mt.New()
  302. }
  303. if err := protoV2.Unmarshal(rawVal, m2.Interface()); err != nil {
  304. return err
  305. }
  306. if wellKnownType(m2.Descriptor().FullName()) == "" {
  307. return w.marshalMessage(m2, indent, typeURL)
  308. }
  309. w.write("{")
  310. if w.Indent != "" {
  311. w.write("\n")
  312. }
  313. if err := w.marshalTypeURL(indent, typeURL); err != nil {
  314. return err
  315. }
  316. w.writeComma()
  317. if w.Indent != "" {
  318. w.write(indent)
  319. w.write(w.Indent)
  320. w.write(`"value": `)
  321. } else {
  322. w.write(`"value":`)
  323. }
  324. if err := w.marshalMessage(m2, indent+w.Indent, ""); err != nil {
  325. return err
  326. }
  327. if w.Indent != "" {
  328. w.write("\n")
  329. w.write(indent)
  330. }
  331. w.write("}")
  332. return nil
  333. }
  334. func (w *jsonWriter) marshalTypeURL(indent, typeURL string) error {
  335. if w.Indent != "" {
  336. w.write(indent)
  337. w.write(w.Indent)
  338. }
  339. w.write(`"@type":`)
  340. if w.Indent != "" {
  341. w.write(" ")
  342. }
  343. b, err := json.Marshal(typeURL)
  344. if err != nil {
  345. return err
  346. }
  347. w.write(string(b))
  348. return nil
  349. }
  350. // marshalField writes field description and value to the Writer.
  351. func (w *jsonWriter) marshalField(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
  352. if w.Indent != "" {
  353. w.write(indent)
  354. w.write(w.Indent)
  355. }
  356. w.write(`"`)
  357. switch {
  358. case fd.IsExtension():
  359. // For message set, use the fname of the message as the extension name.
  360. name := string(fd.FullName())
  361. if isMessageSet(fd.ContainingMessage()) {
  362. name = strings.TrimSuffix(name, ".message_set_extension")
  363. }
  364. w.write("[" + name + "]")
  365. case w.OrigName:
  366. name := string(fd.Name())
  367. if fd.Kind() == protoreflect.GroupKind {
  368. name = string(fd.Message().Name())
  369. }
  370. w.write(name)
  371. default:
  372. w.write(string(fd.JSONName()))
  373. }
  374. w.write(`":`)
  375. if w.Indent != "" {
  376. w.write(" ")
  377. }
  378. return w.marshalValue(fd, v, indent)
  379. }
  380. func (w *jsonWriter) marshalValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
  381. switch {
  382. case fd.IsList():
  383. w.write("[")
  384. comma := ""
  385. lv := v.List()
  386. for i := 0; i < lv.Len(); i++ {
  387. w.write(comma)
  388. if w.Indent != "" {
  389. w.write("\n")
  390. w.write(indent)
  391. w.write(w.Indent)
  392. w.write(w.Indent)
  393. }
  394. if err := w.marshalSingularValue(fd, lv.Get(i), indent+w.Indent); err != nil {
  395. return err
  396. }
  397. comma = ","
  398. }
  399. if w.Indent != "" {
  400. w.write("\n")
  401. w.write(indent)
  402. w.write(w.Indent)
  403. }
  404. w.write("]")
  405. return nil
  406. case fd.IsMap():
  407. kfd := fd.MapKey()
  408. vfd := fd.MapValue()
  409. mv := v.Map()
  410. // Collect a sorted list of all map keys and values.
  411. type entry struct{ key, val protoreflect.Value }
  412. var entries []entry
  413. mv.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool {
  414. entries = append(entries, entry{k.Value(), v})
  415. return true
  416. })
  417. sort.Slice(entries, func(i, j int) bool {
  418. switch kfd.Kind() {
  419. case protoreflect.BoolKind:
  420. return !entries[i].key.Bool() && entries[j].key.Bool()
  421. case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind, protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
  422. return entries[i].key.Int() < entries[j].key.Int()
  423. case protoreflect.Uint32Kind, protoreflect.Fixed32Kind, protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
  424. return entries[i].key.Uint() < entries[j].key.Uint()
  425. case protoreflect.StringKind:
  426. return entries[i].key.String() < entries[j].key.String()
  427. default:
  428. panic("invalid kind")
  429. }
  430. })
  431. w.write(`{`)
  432. comma := ""
  433. for _, entry := range entries {
  434. w.write(comma)
  435. if w.Indent != "" {
  436. w.write("\n")
  437. w.write(indent)
  438. w.write(w.Indent)
  439. w.write(w.Indent)
  440. }
  441. s := fmt.Sprint(entry.key.Interface())
  442. b, err := json.Marshal(s)
  443. if err != nil {
  444. return err
  445. }
  446. w.write(string(b))
  447. w.write(`:`)
  448. if w.Indent != "" {
  449. w.write(` `)
  450. }
  451. if err := w.marshalSingularValue(vfd, entry.val, indent+w.Indent); err != nil {
  452. return err
  453. }
  454. comma = ","
  455. }
  456. if w.Indent != "" {
  457. w.write("\n")
  458. w.write(indent)
  459. w.write(w.Indent)
  460. }
  461. w.write(`}`)
  462. return nil
  463. default:
  464. return w.marshalSingularValue(fd, v, indent)
  465. }
  466. }
  467. func (w *jsonWriter) marshalSingularValue(fd protoreflect.FieldDescriptor, v protoreflect.Value, indent string) error {
  468. switch {
  469. case !v.IsValid():
  470. w.write("null")
  471. return nil
  472. case fd.Message() != nil:
  473. return w.marshalMessage(v.Message(), indent+w.Indent, "")
  474. case fd.Enum() != nil:
  475. if fd.Enum().FullName() == "google.protobuf.NullValue" {
  476. w.write("null")
  477. return nil
  478. }
  479. vd := fd.Enum().Values().ByNumber(v.Enum())
  480. if vd == nil || w.EnumsAsInts {
  481. w.write(strconv.Itoa(int(v.Enum())))
  482. } else {
  483. w.write(`"` + string(vd.Name()) + `"`)
  484. }
  485. return nil
  486. default:
  487. switch v.Interface().(type) {
  488. case float32, float64:
  489. switch {
  490. case math.IsInf(v.Float(), +1):
  491. w.write(`"Infinity"`)
  492. return nil
  493. case math.IsInf(v.Float(), -1):
  494. w.write(`"-Infinity"`)
  495. return nil
  496. case math.IsNaN(v.Float()):
  497. w.write(`"NaN"`)
  498. return nil
  499. }
  500. case int64, uint64:
  501. w.write(fmt.Sprintf(`"%d"`, v.Interface()))
  502. return nil
  503. }
  504. b, err := json.Marshal(v.Interface())
  505. if err != nil {
  506. return err
  507. }
  508. w.write(string(b))
  509. return nil
  510. }
  511. }