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  }