...

Source file src/google.golang.org/protobuf/encoding/protojson/encode.go

Documentation: google.golang.org/protobuf/encoding/protojson

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

View as plain text