/* (c) 2019 dr. Sybren A. Stüvel * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package bunqapi import ( "fmt" "reflect" ) // MergeStructs merges an array of structs into a single struct. // The 'responses' argument has to be an array of type X. // The 'mergedResp' has to be a pointer to an instance of type X. func MergeStructs(responses interface{}, mergedResp interface{}) { arrayType := reflect.TypeOf(responses) if arrayType.Kind() != reflect.Slice && arrayType.Kind() != reflect.Array { panic(fmt.Sprintf("responses should be a slice or array, not %v", arrayType.Kind())) } responsesValue := reflect.ValueOf(responses) numResponses := responsesValue.Len() respType := arrayType.Elem() numFields := respType.NumField() resultType := reflect.TypeOf(mergedResp) if resultType.Elem() != respType { panic(fmt.Sprintf("mergedResp should be *%v, not %v", respType, reflect.TypeOf(mergedResp))) } resultValue := reflect.ValueOf(mergedResp).Elem() for index := 0; index < numResponses; index++ { // fmt.Printf("response #%d:\n", index) responseValue := responsesValue.Index(index) for fieldnum := 0; fieldnum < numFields; fieldnum++ { // field := respType.Field(fieldnum) fieldVal := responseValue.Field(fieldnum) // Skip unexported fields. if !fieldVal.CanSet() { continue } // fmt.Printf(" - field %d: %10v ", fieldnum, field.Name) useValue := false switch fieldVal.Kind() { case reflect.Ptr: useValue = !fieldVal.IsNil() // fmt.Printf("is pointer: %v", useValue) case reflect.String: useValue = fieldVal.String() != "" // fmt.Printf("is string : %v", useValue) case reflect.Bool: useValue = fieldVal.Bool() // fmt.Printf("is bool : %v", useValue) default: // fmt.Printf("is kind : %v (not using)", fieldVal.Kind()) } // fmt.Println() if !useValue { continue } resultField := resultValue.Field(fieldnum) resultField.Set(fieldVal) } } }