github.com/kaleido-io/firefly@v0.0.0-20210622132723-8b4b6aacb971/pkg/fftypes/jsondata.go (about) 1 // Copyright © 2021 Kaleido, Inc. 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 package fftypes 18 19 import ( 20 "context" 21 "crypto/sha256" 22 "database/sql/driver" 23 "encoding/json" 24 25 "github.com/kaleido-io/firefly/internal/i18n" 26 "github.com/kaleido-io/firefly/internal/log" 27 ) 28 29 // JSONObject is a holder of a hash, that can be used to correlate onchain data with off-chain data. 30 type JSONObject map[string]interface{} 31 32 // Scan implements sql.Scanner 33 func (jd *JSONObject) Scan(src interface{}) error { 34 switch src := src.(type) { 35 case nil: 36 return nil 37 38 case string, []byte: 39 if src == "" { 40 return nil 41 } 42 return json.Unmarshal(src.([]byte), &jd) 43 44 default: 45 return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, jd) 46 } 47 48 } 49 50 func (jd JSONObject) GetString(key string) string { 51 s, _ := jd.GetStringOk(key) 52 return s 53 } 54 55 func (jd JSONObject) GetStringOk(key string) (string, bool) { 56 vInterace, ok := jd[key] 57 if ok && vInterace != nil { 58 if vString, ok := vInterace.(string); ok { 59 return vString, true 60 } 61 log.L(context.Background()).Errorf("Invalid string value '%+v' for key '%s'", vInterace, key) 62 } 63 return "", false 64 } 65 66 func (jd JSONObject) GetObject(key string) JSONObject { 67 ob, _ := jd.GetObjectOk(key) 68 return ob 69 } 70 71 func (jd JSONObject) GetObjectOk(key string) (JSONObject, bool) { 72 vInterace, ok := jd[key] 73 if ok && vInterace != nil { 74 if vMap, ok := vInterace.(map[string]interface{}); ok { 75 return JSONObject(vMap), true 76 } 77 } 78 log.L(context.Background()).Errorf("Invalid object value '%+v' for key '%s'", vInterace, key) 79 return JSONObject{}, false // Ensures a non-nil return 80 } 81 82 func ToJSONObjectArray(unknown interface{}) (JSONObjectArray, bool) { 83 vMap, ok := unknown.([]interface{}) 84 joa := make(JSONObjectArray, len(vMap)) 85 if !ok { 86 joa, ok = unknown.(JSONObjectArray) // Case that we're passed a JSONObjectArray directly 87 } 88 for i, joi := range vMap { 89 jo, childOK := joi.(map[string]interface{}) 90 if childOK { 91 joa[i] = JSONObject(jo) 92 } 93 ok = ok && childOK 94 } 95 return joa, ok 96 } 97 98 func ToStringArray(unknown interface{}) ([]string, bool) { 99 vArray, ok := unknown.([]interface{}) 100 joa := make([]string, len(vArray)) 101 if !ok { 102 joa, ok = unknown.([]string) // Case that we're passed a []string directly 103 } 104 for i, joi := range vArray { 105 jo, childOK := joi.(string) 106 if childOK { 107 joa[i] = jo 108 } 109 ok = ok && childOK 110 } 111 return joa, ok 112 } 113 114 func (jd JSONObject) GetObjectArray(key string) JSONObjectArray { 115 oa, _ := jd.GetObjectArrayOk(key) 116 return oa 117 } 118 119 func (jd JSONObject) GetObjectArrayOk(key string) (JSONObjectArray, bool) { 120 vInterace, ok := jd[key] 121 if ok && vInterace != nil { 122 return ToJSONObjectArray(vInterace) 123 } 124 log.L(context.Background()).Errorf("Invalid object value '%+v' for key '%s'", vInterace, key) 125 return JSONObjectArray{}, false // Ensures a non-nil return 126 } 127 128 func (jd JSONObject) GetStringArray(key string) []string { 129 sa, _ := jd.GetStringArrayOk(key) 130 return sa 131 } 132 133 func (jd JSONObject) GetStringArrayOk(key string) ([]string, bool) { 134 vInterace, ok := jd[key] 135 if ok && vInterace != nil { 136 return ToStringArray(vInterace) 137 } 138 log.L(context.Background()).Errorf("Invalid string array value '%+v' for key '%s'", vInterace, key) 139 return []string{}, false // Ensures a non-nil return 140 } 141 142 // Value implements sql.Valuer 143 func (jd JSONObject) Value() (driver.Value, error) { 144 return json.Marshal(&jd) 145 } 146 147 func (jd JSONObject) String() string { 148 b, _ := json.Marshal(&jd) 149 return string(b) 150 } 151 152 func (jd JSONObject) Hash(jsonDesc string) (*Bytes32, error) { 153 b, err := json.Marshal(&jd) 154 if err != nil { 155 return nil, i18n.NewError(context.Background(), i18n.MsgJSONObjectParseFailed, jsonDesc) 156 } 157 var b32 Bytes32 = sha256.Sum256(b) 158 return &b32, nil 159 } 160 161 // JSONObjectArray is an array of JSONObject 162 type JSONObjectArray []JSONObject 163 164 // Scan implements sql.Scanner 165 func (jd *JSONObjectArray) Scan(src interface{}) error { 166 switch src := src.(type) { 167 case nil: 168 return nil 169 170 case string, []byte: 171 if src == "" { 172 return nil 173 } 174 return json.Unmarshal(src.([]byte), &jd) 175 176 default: 177 return i18n.NewError(context.Background(), i18n.MsgScanFailed, src, jd) 178 } 179 180 } 181 182 func (jd JSONObjectArray) Value() (driver.Value, error) { 183 return json.Marshal(&jd) 184 } 185 186 func (jd JSONObjectArray) String() string { 187 b, _ := json.Marshal(&jd) 188 return string(b) 189 } 190 191 func (jd JSONObjectArray) Hash(jsonDesc string) (*Bytes32, error) { 192 b, err := json.Marshal(&jd) 193 if err != nil { 194 return nil, i18n.NewError(context.Background(), i18n.MsgJSONObjectParseFailed, jsonDesc) 195 } 196 var b32 Bytes32 = sha256.Sum256(b) 197 return &b32, nil 198 }