github.com/kaituanwang/hyperledger@v2.0.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 }