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  }