github.com/TIBCOSoftware/flogo-lib@v0.5.9/core/mapper/exprmapper/json/get.go (about)

     1  package json
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/TIBCOSoftware/flogo-lib/core/mapper/exprmapper/json/field"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"sync"
    10  
    11  	"encoding/json"
    12  	"github.com/TIBCOSoftware/flogo-lib/logger"
    13  )
    14  
    15  var log = logger.GetLogger("json")
    16  
    17  func GetPathValue(value interface{}, refPath string) (interface{}, error) {
    18  	mappingField, err := field.ParseMappingField(refPath)
    19  	if err != nil {
    20  		return nil, fmt.Errorf("parse mapping path [%s] failed, due to %s", refPath, err.Error())
    21  	}
    22  
    23  	if mappingField == nil || len(mappingField.Getfields()) <= 0 {
    24  		value, err := makeInterface(value)
    25  		if err != nil {
    26  			value = value
    27  		}
    28  		return value, nil
    29  	}
    30  	return GetFieldValue(value, mappingField)
    31  }
    32  
    33  func GetFieldValue(data interface{}, mappingField *field.MappingField) (interface{}, error) {
    34  	var jsonParsed *Container
    35  	var err error
    36  	switch data.(type) {
    37  	case string:
    38  		jsonParsed, err = ParseJSON([]byte(data.(string)))
    39  	default:
    40  		if IsMapperableType(data) {
    41  			jsonParsed, err = Consume(data)
    42  		} else {
    43  			//Take is as string to handle
    44  			b, err := json.Marshal(data)
    45  			if err != nil {
    46  				return nil, err
    47  			}
    48  			jsonParsed, err = ParseJSON(b)
    49  		}
    50  	}
    51  
    52  	if err != nil {
    53  		return nil, err
    54  
    55  	}
    56  	return handleGetValue(&JSONData{container: jsonParsed, rw: sync.RWMutex{}}, mappingField.Getfields())
    57  }
    58  
    59  func handleGetValue(jsonData *JSONData, fields []string) (interface{}, error) {
    60  	jsonData.rw.Lock()
    61  	defer jsonData.rw.Unlock()
    62  
    63  	container := jsonData.container
    64  	if hasArrayFieldInArray(fields) {
    65  		arrayFields, fieldNameindex, arrayIndex := getArrayFieldName(fields)
    66  		//No array field found
    67  		if fieldNameindex == -1 {
    68  			return container.S(arrayFields...).Data(), nil
    69  		}
    70  		restFields := fields[fieldNameindex+1:]
    71  		specialField, err := container.ArrayElement(arrayIndex, arrayFields...)
    72  		if err != nil {
    73  			return nil, err
    74  		}
    75  		log.Debugf("Array element value %s", specialField)
    76  		if hasArrayFieldInArray(restFields) {
    77  			return handleGetValue(&JSONData{container: specialField, rw: sync.RWMutex{}}, restFields)
    78  		}
    79  		return specialField.S(restFields...).Data(), nil
    80  	}
    81  	return container.S(fields...).Data(), nil
    82  }
    83  
    84  func getFieldName(fieldName string) string {
    85  	if strings.Index(fieldName, "[") >= 0 {
    86  		return fieldName[0:strings.Index(fieldName, "[")]
    87  	}
    88  
    89  	return fieldName
    90  }
    91  
    92  func getFieldSliceIndex(fieldName string) (int, error) {
    93  	if strings.Index(fieldName, "[") >= 0 {
    94  		index := fieldName[strings.Index(fieldName, "[")+1 : strings.Index(fieldName, "]")]
    95  		i, err := strconv.Atoi(index)
    96  
    97  		if err != nil {
    98  			return -2, nil
    99  		}
   100  		return i, nil
   101  	}
   102  
   103  	return -1, nil
   104  }
   105  
   106  func getNameInsideBrancket(fieldName string) string {
   107  	if strings.Index(fieldName, "[") >= 0 {
   108  		index := fieldName[strings.Index(fieldName, "[")+1 : strings.Index(fieldName, "]")]
   109  		return index
   110  	}
   111  
   112  	return ""
   113  }
   114  
   115  func makeInterface(value interface{}) (interface{}, error) {
   116  
   117  	var paramMap interface{}
   118  
   119  	if value == nil {
   120  		return paramMap, nil
   121  	}
   122  
   123  	switch t := value.(type) {
   124  	case string:
   125  		err := json.Unmarshal([]byte(t), &paramMap)
   126  		if err != nil {
   127  			return nil, err
   128  		}
   129  		return paramMap, nil
   130  	default:
   131  		return value, nil
   132  	}
   133  	return paramMap, nil
   134  }
   135  
   136  func getArrayFieldName(fields []string) ([]string, int, int) {
   137  	var tmpFields []string
   138  	index := -1
   139  	var arrayIndex int
   140  	for i, field := range fields {
   141  		if strings.Index(field, "[") >= 0 && strings.Index(field, "]") >= 0 {
   142  			arrayIndex, _ = getFieldSliceIndex(field)
   143  			fieldName := getFieldName(field)
   144  			index = i
   145  			if fieldName != "" {
   146  				tmpFields = append(tmpFields, getFieldName(field))
   147  			}
   148  			break
   149  		} else {
   150  			tmpFields = append(tmpFields, field)
   151  		}
   152  	}
   153  	return tmpFields, index, arrayIndex
   154  }
   155  
   156  func hasArrayFieldInArray(fields []string) bool {
   157  	for _, field := range fields {
   158  		if strings.Index(field, "[") >= 0 && strings.HasSuffix(field, "]") {
   159  			//Make sure the index are integer
   160  			_, err := strconv.Atoi(getNameInsideBrancket(field))
   161  			if err == nil {
   162  				return true
   163  			}
   164  		}
   165  	}
   166  	return false
   167  }