github.com/pvitto98/fabric@v2.1.1+incompatible/common/tools/protolator/json.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package protolator
     8  
     9  import (
    10  	"bytes"
    11  	"encoding/json"
    12  	"fmt"
    13  	"io"
    14  	"io/ioutil"
    15  	"reflect"
    16  
    17  	"github.com/golang/protobuf/jsonpb"
    18  	"github.com/golang/protobuf/proto"
    19  	"github.com/hyperledger/fabric/common/tools/protolator/protoext"
    20  )
    21  
    22  // MostlyDeterministicMarshal is _NOT_ the function you are looking for.
    23  // It causes protobuf serialization consistent within a single build.  It
    24  // does not guarantee that the serialization is deterministic across proto
    25  // versions or proto implementations.  It is useful for situations where
    26  // the same process wants to compare binary messages for equality without
    27  // needing to unmarshal first, but should not be used generally.
    28  func MostlyDeterministicMarshal(msg proto.Message) ([]byte, error) {
    29  	buffer := proto.NewBuffer(make([]byte, 0))
    30  	buffer.SetDeterministic(true)
    31  	if err := buffer.Marshal(msg); err != nil {
    32  		return nil, err
    33  	}
    34  	return buffer.Bytes(), nil
    35  }
    36  
    37  type protoFieldFactory interface {
    38  	// Handles should return whether or not this particular protoFieldFactory instance
    39  	// is responsible for the given proto's field
    40  	Handles(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) bool
    41  
    42  	// NewProtoField should create a backing protoField implementor
    43  	// Note that the fieldValue may represent nil, so the fieldType is also
    44  	// included (as reflecting the type of a nil value causes a panic)
    45  	NewProtoField(msg proto.Message, fieldName string, fieldType reflect.Type, fieldValue reflect.Value) (protoField, error)
    46  }
    47  
    48  type protoField interface {
    49  	// Name returns the proto name of the field
    50  	Name() string
    51  
    52  	// PopulateFrom mutates the underlying object, by taking the intermediate JSON representation
    53  	// and converting it into the proto representation, then assigning it to the backing value
    54  	// via reflection
    55  	PopulateFrom(source interface{}) error
    56  
    57  	// PopulateTo does not mutate the underlying object, but instead converts it
    58  	// into the intermediate JSON representation (ie a struct -> map[string]interface{}
    59  	// or a slice of structs to []map[string]interface{}
    60  	PopulateTo() (interface{}, error)
    61  }
    62  
    63  var (
    64  	protoMsgType           = reflect.TypeOf((*proto.Message)(nil)).Elem()
    65  	mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
    66  	bytesType              = reflect.TypeOf([]byte{})
    67  )
    68  
    69  type baseField struct {
    70  	msg   proto.Message
    71  	name  string
    72  	fType reflect.Type
    73  	vType reflect.Type
    74  	value reflect.Value
    75  }
    76  
    77  func (bf *baseField) Name() string {
    78  	return bf.name
    79  }
    80  
    81  type plainField struct {
    82  	baseField
    83  	populateFrom func(source interface{}, destType reflect.Type) (reflect.Value, error)
    84  	populateTo   func(source reflect.Value) (interface{}, error)
    85  }
    86  
    87  func (pf *plainField) PopulateFrom(source interface{}) error {
    88  	if source == nil {
    89  		return nil
    90  	}
    91  
    92  	if !reflect.TypeOf(source).AssignableTo(pf.fType) {
    93  		return fmt.Errorf("expected field %s for message %T to be assignable from %v but was not.  Is %T", pf.name, pf.msg, pf.fType, source)
    94  	}
    95  	value, err := pf.populateFrom(source, pf.vType)
    96  	if err != nil {
    97  		return fmt.Errorf("error in PopulateFrom for field %s for message %T: %s", pf.name, pf.msg, err)
    98  	}
    99  	pf.value.Set(value)
   100  	return nil
   101  }
   102  
   103  func (pf *plainField) PopulateTo() (interface{}, error) {
   104  	if !pf.value.Type().AssignableTo(pf.vType) {
   105  		return nil, fmt.Errorf("expected field %s for message %T to be assignable to %v but was not. Got %T.", pf.name, pf.msg, pf.fType, pf.value)
   106  	}
   107  
   108  	kind := pf.value.Type().Kind()
   109  	// Do not try to deeply encode nil fields, as without correct type info etc. they
   110  	// may return errors
   111  	if (kind == reflect.Ptr || kind == reflect.Slice || kind == reflect.Map) && pf.value.IsNil() {
   112  		return nil, nil
   113  	}
   114  
   115  	value, err := pf.populateTo(pf.value)
   116  	if err != nil {
   117  		return nil, fmt.Errorf("error in PopulateTo for field %s for message %T: %s", pf.name, pf.msg, err)
   118  	}
   119  	return value, nil
   120  }
   121  
   122  type mapField struct {
   123  	baseField
   124  	populateFrom func(key string, value interface{}, destType reflect.Type) (reflect.Value, error)
   125  	populateTo   func(key string, value reflect.Value) (interface{}, error)
   126  }
   127  
   128  func (mf *mapField) PopulateFrom(source interface{}) error {
   129  	tree, ok := source.(map[string]interface{})
   130  	if !ok {
   131  		return fmt.Errorf("expected map field %s for message %T to be assignable from map[string]interface{} but was not. Got %T", mf.name, mf.msg, source)
   132  	}
   133  
   134  	result := reflect.MakeMap(mf.vType)
   135  
   136  	for k, v := range tree {
   137  		if !reflect.TypeOf(v).AssignableTo(mf.fType) {
   138  			return fmt.Errorf("expected map field %s value for %s for message %T to be assignable from %v but was not.  Is %T", mf.name, k, mf.msg, mf.fType, v)
   139  		}
   140  		newValue, err := mf.populateFrom(k, v, mf.vType.Elem())
   141  		if err != nil {
   142  			return fmt.Errorf("error in PopulateFrom for map field %s with key %s for message %T: %s", mf.name, k, mf.msg, err)
   143  		}
   144  		result.SetMapIndex(reflect.ValueOf(k), newValue)
   145  	}
   146  
   147  	mf.value.Set(result)
   148  	return nil
   149  }
   150  
   151  func (mf *mapField) PopulateTo() (interface{}, error) {
   152  	result := make(map[string]interface{})
   153  	keys := mf.value.MapKeys()
   154  	for _, key := range keys {
   155  		k, ok := key.Interface().(string)
   156  		if !ok {
   157  			return nil, fmt.Errorf("expected map field %s for message %T to have string keys, but did not.", mf.name, mf.msg)
   158  		}
   159  
   160  		subValue := mf.value.MapIndex(key)
   161  		kind := subValue.Type().Kind()
   162  		if (kind == reflect.Ptr || kind == reflect.Slice || kind == reflect.Map) && subValue.IsNil() {
   163  			continue
   164  		}
   165  
   166  		if !subValue.Type().AssignableTo(mf.vType.Elem()) {
   167  			return nil, fmt.Errorf("expected map field %s with key %s for message %T to be assignable to %v but was not. Got %v.", mf.name, k, mf.msg, mf.vType.Elem(), subValue.Type())
   168  		}
   169  
   170  		value, err := mf.populateTo(k, subValue)
   171  		if err != nil {
   172  			return nil, fmt.Errorf("error in PopulateTo for map field %s and key %s for message %T: %s", mf.name, k, mf.msg, err)
   173  		}
   174  		result[k] = value
   175  	}
   176  
   177  	return result, nil
   178  }
   179  
   180  type sliceField struct {
   181  	baseField
   182  	populateTo   func(i int, source reflect.Value) (interface{}, error)
   183  	populateFrom func(i int, source interface{}, destType reflect.Type) (reflect.Value, error)
   184  }
   185  
   186  func (sf *sliceField) PopulateFrom(source interface{}) error {
   187  	slice, ok := source.([]interface{})
   188  	if !ok {
   189  		return fmt.Errorf("expected slice field %s for message %T to be assignable from []interface{} but was not. Got %T", sf.name, sf.msg, source)
   190  	}
   191  
   192  	result := reflect.MakeSlice(sf.vType, len(slice), len(slice))
   193  
   194  	for i, v := range slice {
   195  		if !reflect.TypeOf(v).AssignableTo(sf.fType) {
   196  			return fmt.Errorf("expected slice field %s value at index %d for message %T to be assignable from %v but was not.  Is %T", sf.name, i, sf.msg, sf.fType, v)
   197  		}
   198  		subValue, err := sf.populateFrom(i, v, sf.vType.Elem())
   199  		if err != nil {
   200  			return fmt.Errorf("error in PopulateFrom for slice field %s at index %d for message %T: %s", sf.name, i, sf.msg, err)
   201  		}
   202  		result.Index(i).Set(subValue)
   203  	}
   204  
   205  	sf.value.Set(result)
   206  	return nil
   207  }
   208  
   209  func (sf *sliceField) PopulateTo() (interface{}, error) {
   210  	result := make([]interface{}, sf.value.Len())
   211  	for i := range result {
   212  		subValue := sf.value.Index(i)
   213  		kind := subValue.Type().Kind()
   214  		if (kind == reflect.Ptr || kind == reflect.Slice || kind == reflect.Map) && subValue.IsNil() {
   215  			continue
   216  		}
   217  
   218  		if !subValue.Type().AssignableTo(sf.vType.Elem()) {
   219  			return nil, fmt.Errorf("expected slice field %s at index %d for message %T to be assignable to %v but was not. Got %v.", sf.name, i, sf.msg, sf.vType.Elem(), subValue.Type())
   220  		}
   221  
   222  		value, err := sf.populateTo(i, subValue)
   223  		if err != nil {
   224  			return nil, fmt.Errorf("error in PopulateTo for slice field %s at index %d for message %T: %s", sf.name, i, sf.msg, err)
   225  		}
   226  		result[i] = value
   227  	}
   228  
   229  	return result, nil
   230  }
   231  
   232  func stringInSlice(target string, slice []string) bool {
   233  	for _, name := range slice {
   234  		if name == target {
   235  			return true
   236  		}
   237  	}
   238  	return false
   239  }
   240  
   241  // protoToJSON is a simple shortcut wrapper around the proto JSON marshaler
   242  func protoToJSON(msg proto.Message) ([]byte, error) {
   243  	if reflect.ValueOf(msg).IsNil() {
   244  		panic("We're nil here")
   245  	}
   246  	var b bytes.Buffer
   247  	m := jsonpb.Marshaler{
   248  		EnumsAsInts:  false,
   249  		EmitDefaults: true,
   250  		Indent:       "  ",
   251  		OrigName:     true,
   252  	}
   253  	err := m.Marshal(&b, msg)
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  	return b.Bytes(), nil
   258  }
   259  
   260  func mapToProto(tree map[string]interface{}, msg proto.Message) error {
   261  	jsonOut, err := json.Marshal(tree)
   262  	if err != nil {
   263  		return err
   264  	}
   265  
   266  	return jsonpb.UnmarshalString(string(jsonOut), msg)
   267  }
   268  
   269  // jsonToMap allocates a map[string]interface{}, unmarshals a JSON document into it
   270  // and returns it, or error
   271  func jsonToMap(marshaled []byte) (map[string]interface{}, error) {
   272  	tree := make(map[string]interface{})
   273  	d := json.NewDecoder(bytes.NewReader(marshaled))
   274  	d.UseNumber()
   275  	err := d.Decode(&tree)
   276  	if err != nil {
   277  		return nil, fmt.Errorf("error unmarshaling intermediate JSON: %s", err)
   278  	}
   279  	return tree, nil
   280  }
   281  
   282  // The factory implementations, listed in order of most greedy to least.
   283  // Factories listed lower, may depend on factories listed higher being
   284  // evaluated first.
   285  var fieldFactories = []protoFieldFactory{
   286  	dynamicSliceFieldFactory{},
   287  	dynamicMapFieldFactory{},
   288  	dynamicFieldFactory{},
   289  	variablyOpaqueSliceFieldFactory{},
   290  	variablyOpaqueMapFieldFactory{},
   291  	variablyOpaqueFieldFactory{},
   292  	staticallyOpaqueSliceFieldFactory{},
   293  	staticallyOpaqueMapFieldFactory{},
   294  	staticallyOpaqueFieldFactory{},
   295  	nestedSliceFieldFactory{},
   296  	nestedMapFieldFactory{},
   297  	nestedFieldFactory{},
   298  }
   299  
   300  func protoFields(msg proto.Message, uMsg proto.Message) ([]protoField, error) {
   301  	var result []protoField
   302  
   303  	pmVal := reflect.ValueOf(uMsg)
   304  	if pmVal.Kind() != reflect.Ptr {
   305  		return nil, fmt.Errorf("expected proto.Message %T to be pointer kind", uMsg)
   306  	}
   307  
   308  	if pmVal.IsNil() {
   309  		return nil, nil
   310  	}
   311  
   312  	mVal := pmVal.Elem()
   313  	if mVal.Kind() != reflect.Struct {
   314  		return nil, fmt.Errorf("expected proto.Message %T ptr value to be struct, was %v", uMsg, mVal.Kind())
   315  	}
   316  
   317  	iResult := make([][]protoField, len(fieldFactories))
   318  
   319  	protoProps := proto.GetProperties(mVal.Type())
   320  	// TODO, this will skip oneof fields, this should be handled
   321  	// correctly at some point
   322  	for _, prop := range protoProps.Prop {
   323  		fieldName := prop.OrigName
   324  		fieldValue := mVal.FieldByName(prop.Name)
   325  		fieldTypeStruct, ok := mVal.Type().FieldByName(prop.Name)
   326  		if !ok {
   327  			return nil, fmt.Errorf("programming error: proto does not have field advertised by proto package")
   328  		}
   329  		fieldType := fieldTypeStruct.Type
   330  
   331  		for i, factory := range fieldFactories {
   332  			if !factory.Handles(msg, fieldName, fieldType, fieldValue) {
   333  				continue
   334  			}
   335  
   336  			field, err := factory.NewProtoField(msg, fieldName, fieldType, fieldValue)
   337  			if err != nil {
   338  				return nil, err
   339  			}
   340  			iResult[i] = append(iResult[i], field)
   341  			break
   342  		}
   343  	}
   344  
   345  	// Loop over the collected fields in reverse order to collect them in
   346  	// correct dependency order as specified in fieldFactories
   347  	for i := len(iResult) - 1; i >= 0; i-- {
   348  		result = append(result, iResult[i]...)
   349  	}
   350  
   351  	return result, nil
   352  }
   353  
   354  func recursivelyCreateTreeFromMessage(msg proto.Message) (tree map[string]interface{}, err error) {
   355  	defer func() {
   356  		// Because this function is recursive, it's difficult to determine which level
   357  		// of the proto the error originated from, this wrapper leaves breadcrumbs for debugging
   358  		if err != nil {
   359  			err = fmt.Errorf("%T: %s", msg, err)
   360  		}
   361  	}()
   362  
   363  	msg = protoext.Decorate(msg)
   364  	uMsg := msg
   365  	if decorated, ok := msg.(DecoratedProto); ok {
   366  		uMsg = decorated.Underlying()
   367  	}
   368  
   369  	fields, err := protoFields(msg, uMsg)
   370  	if err != nil {
   371  		return nil, err
   372  	}
   373  
   374  	jsonBytes, err := protoToJSON(uMsg)
   375  	if err != nil {
   376  		return nil, err
   377  	}
   378  
   379  	tree, err = jsonToMap(jsonBytes)
   380  	if err != nil {
   381  		return nil, err
   382  	}
   383  
   384  	for _, field := range fields {
   385  		if _, ok := tree[field.Name()]; !ok {
   386  			continue
   387  		}
   388  		delete(tree, field.Name())
   389  		tree[field.Name()], err = field.PopulateTo()
   390  		if err != nil {
   391  			return nil, err
   392  		}
   393  	}
   394  
   395  	return tree, nil
   396  }
   397  
   398  // DeepMarshalJSON marshals msg to w as JSON, but instead of marshaling bytes fields which contain nested
   399  // marshaled messages as base64 (like the standard proto encoding), these nested messages are remarshaled
   400  // as the JSON representation of those messages.  This is done so that the JSON representation is as non-binary
   401  // and human readable as possible.
   402  func DeepMarshalJSON(w io.Writer, msg proto.Message) error {
   403  	root, err := recursivelyCreateTreeFromMessage(msg)
   404  	if err != nil {
   405  		return err
   406  	}
   407  
   408  	encoder := json.NewEncoder(w)
   409  	encoder.SetIndent("", "\t")
   410  	return encoder.Encode(root)
   411  }
   412  
   413  func recursivelyPopulateMessageFromTree(tree map[string]interface{}, msg proto.Message) (err error) {
   414  	defer func() {
   415  		// Because this function is recursive, it's difficult to determine which level
   416  		// of the proto the error orginated from, this wrapper leaves breadcrumbs for debugging
   417  		if err != nil {
   418  			err = fmt.Errorf("%T: %s", msg, err)
   419  		}
   420  	}()
   421  
   422  	msg = protoext.Decorate(msg)
   423  	uMsg := msg
   424  	if decorated, ok := msg.(DecoratedProto); ok {
   425  		uMsg = decorated.Underlying()
   426  	}
   427  
   428  	fields, err := protoFields(msg, uMsg)
   429  	if err != nil {
   430  		return err
   431  	}
   432  
   433  	specialFieldsMap := make(map[string]interface{})
   434  
   435  	for _, field := range fields {
   436  		specialField, ok := tree[field.Name()]
   437  		if !ok {
   438  			continue
   439  		}
   440  		specialFieldsMap[field.Name()] = specialField
   441  		delete(tree, field.Name())
   442  	}
   443  
   444  	if err = mapToProto(tree, uMsg); err != nil {
   445  		return err
   446  	}
   447  
   448  	for _, field := range fields {
   449  		specialField, ok := specialFieldsMap[field.Name()]
   450  		if !ok {
   451  			continue
   452  		}
   453  		if err := field.PopulateFrom(specialField); err != nil {
   454  			return err
   455  		}
   456  	}
   457  
   458  	return nil
   459  }
   460  
   461  // DeepUnmarshalJSON takes JSON output as generated by DeepMarshalJSON and decodes it into msg
   462  // This includes re-marshaling the expanded nested elements to binary form
   463  func DeepUnmarshalJSON(r io.Reader, msg proto.Message) error {
   464  	b, err := ioutil.ReadAll(r)
   465  	if err != nil {
   466  		return err
   467  	}
   468  
   469  	root, err := jsonToMap(b)
   470  	if err != nil {
   471  		return err
   472  	}
   473  
   474  	return recursivelyPopulateMessageFromTree(root, msg)
   475  }