github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/util/json/json.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 SPDX-License-Identifier: Apache-2.0 4 */ 5 6 package json 7 8 import ( 9 "encoding/json" 10 ) 11 12 // MarshalWithCustomFields marshals value merged with custom fields defined in the map into JSON bytes. 13 func MarshalWithCustomFields(v interface{}, cf map[string]interface{}) ([]byte, error) { 14 // Merge value and custom fields into the joint map. 15 vm, err := MergeCustomFields(v, cf) 16 if err != nil { 17 return nil, err 18 } 19 20 // Marshal the joint map. 21 return json.Marshal(vm) 22 } 23 24 // UnmarshalWithCustomFields unmarshals JSON into value v and puts all JSON fields which do not belong to value 25 // into custom fields map cf. 26 func UnmarshalWithCustomFields(data []byte, v interface{}, cf map[string]interface{}) error { 27 err := json.Unmarshal(data, v) 28 if err != nil { 29 return err 30 } 31 32 // Collect value fields map. 33 vData, err := json.Marshal(v) 34 if err != nil { 35 return err 36 } 37 38 var vf map[string]interface{} 39 40 err = json.Unmarshal(vData, &vf) 41 if err != nil { 42 return err 43 } 44 45 // Collect all fields map. 46 var af map[string]interface{} 47 48 err = json.Unmarshal(data, &af) 49 if err != nil { 50 return err 51 } 52 53 // Copy only those entries which do not belong to the value (i.e. custom fields). 54 for k, v := range af { 55 if _, ok := vf[k]; !ok { 56 cf[k] = v 57 } 58 } 59 60 return nil 61 } 62 63 // MergeCustomFields converts value to the JSON-like map and merges it with custom fields map cf. 64 func MergeCustomFields(v interface{}, cf map[string]interface{}) (map[string]interface{}, error) { 65 kf, err := ToMap(v) 66 if err != nil { 67 return nil, err 68 } 69 70 // Supplement value map with custom fields. 71 for k, v := range cf { 72 if _, exists := kf[k]; !exists { 73 kf[k] = v 74 } 75 } 76 77 return kf, nil 78 } 79 80 // ToMap convert object, string or bytes to json object represented by map. 81 func ToMap(v interface{}) (map[string]interface{}, error) { 82 var ( 83 b []byte 84 err error 85 ) 86 87 switch cv := v.(type) { 88 case []byte: 89 b = cv 90 case string: 91 b = []byte(cv) 92 default: 93 b, err = json.Marshal(v) 94 if err != nil { 95 return nil, err 96 } 97 } 98 99 var m map[string]interface{} 100 101 err = json.Unmarshal(b, &m) 102 if err != nil { 103 return nil, err 104 } 105 106 return m, nil 107 } 108 109 // ToMaps convert array to array of json objects. 110 func ToMaps(v []interface{}) ([]map[string]interface{}, error) { 111 maps := make([]map[string]interface{}, len(v)) 112 113 for i := range v { 114 m, err := ToMap(v[i]) 115 if err != nil { 116 return nil, err 117 } 118 119 maps[i] = m 120 } 121 122 return maps, nil 123 }