How to Iterate and update struct values from one struct to another

Hi All,
I have a use case where i want to use the values from one struct (which i get from unmarshaling a json file). I then basically want to use the value of this struct to loop over another struct (which consists of a empty template- used unmarshaling as well). I tried looking at the articles online but was not of much help. Any pointers would be appreciated. Here is the code for you reference.

FYI- i am able to get the required values as expected. I just need a way to take values of one struct, iterate over the original struct and update its value.

#This struct below returns a template file where fields are empty- which i want to update with values from TemplateTwo struct below
type Template struct {
	General struct {
		ShowName string                        `json:”showName"`
		Fields      map[string]XYZField `json:"fields"`
	} `json:"xyz"`
}

type XYZField struct {
	ShowName  string   `json:”showName"`
	Required     bool     `json:"required"`
}

type FirstOne struct {
	Xyz TemplateXyz  `json:”xyz”`
}

type showName struct {
	firstName    string `json:”firstName" binding:"required,excludesall=!@#$%^&*()<>?+{}[]"`
	Address string `json:"Address" binding:"required,excludesall=!@#$%^&*()<>?+{}[]"`
}

#this  is the 2nd struct below returns a template with fields which can be filled - I need to find a way to take the values of 
This struct below and loop the values to the Template struct above, so if there are fields filled here, it gets populated in the struct above as well
type TemplateTwo struct {
	Xyz map[string] interface{} `json:”XYZ”`
}

err = json.Unmarshal(Form, &TemplateTwo)
if err !=nil{
	logger.Errorf(“Erro msg”)
}

reflectValue := reflect.ValueOf(TemplateTwo)
typeOfValue := reflectValue.Type()

for i := 0; i< reflectValue.NumField(); i++ {
	fmt.Printf("Field: %s\tValue: %v\n", typeOfValue.Field(i).Name, reflectValue.Field(i).Interface())
}

Hi, @Contra_Boy, can you edit your post and re-paste your code within code blocks?

To create a code block, wrap your code with ```

For example:

```
code
```

Hi @skillian, I edited the post as you suggested. Thanks!

look over struct fields ?

https://play.golang.org/p/GZcw9BmcNHd

package main

import (
	"fmt"
	"reflect"
)

type showName struct {
	FirstName string `json:"firstName" binding:"required,excludesall=!@#$%^&*()<>?+{}[]"`
	Address   string `json:"Address" binding:"required,excludesall=!@#$%^&*()<>?+{}[]"`
}

func main() {
	fmt.Println("Hello, playground")
	var i = &showName{
		FirstName: "ss",
		// your set fields
	}
	// because i is showName ptr type, use Elem method remove pinter.
	iType := reflect.TypeOf(i).Elem()
	iValue := reflect.ValueOf(i).Elem()
	for _, name := range []string{"FirstName", "b"} {
		// no check tag, need look over all fields tag match your tag.
		fieldType, ok := iType.FieldByName(name)
		if !ok {
			// not find name field
			continue
		}
		fmt.Println(fieldType.Name, fieldType.Tag, iValue.FieldByName(name).Interface())
	}

}

It looks like your use case might be similar to the one I tried to answer in another thread here: Convert string to nested structure. Do any of those solutions work for you?

Hi, Thanks for the reply. But i already have the values i need to update on the other struct which are json values. I am just trying to figure out a way to get the list of keys of my struct (which is a map[string] interface) and take those values and loop,replace the empty values in my other struct.

Hi, @Contra_Boy, I’m sorry, but I do not yet understand what you’re trying to do. It sounds like you have two JSON files and you want to merge the data from one JSON file into the other if the field names overlap. Is that right?

Yes that is right. The only difference being that i need to reflect the updates values on the structs level as that is what my function should return and not the file

@Contra_Boy can’t you just unmarshal the two JSON files to the same model? https://play.golang.org/p/bRaASBMVPju? The second one should only update the first.

This is a good solution, only issue being the json are grabbed on the fly while the endpoint is being invoked.
Is there a way to implement the below code when jsons are grabbed on the fly?

const (
	primaryJSON = `{
	"FirstName": "Sean",
	"Address": "123 Street Rd. Bensalem, PA  19020"
}`

	deltaJSON = `{
	"FirstName": "Bob"
}`
)

Also, the values are dynamic for delta Json , and the file structure for both json is different as well

@Contra_Boy let’s try this: Can you provide sample source JSON files and then a sample of what you want the result to look like?

EDIT: Asking because I’m a little mixed up on what you mean by “the values are dynamic for delta Json” but that you need the data in structs; you can’t have dynamic structs in Go, so I’m having a hard time understanding the use case.

Here you go, so basically all the updated data in Secondary file needs to be reflected in the primary file.

Primary file:
{
  "general": {
    "displayName": "Information",
    "fields": {
      "company": {
        "type": "text",
        "currentValue": "",
        "displayName": "Company Name",
        "required": true
      },
      "streetAddress1": {
        "type": "text",
        "currentValue": "",
        "displayName": "Street Address",
        "required": true
      },
      "streetAddress2": {
        "type": "text",
        "currentValue": "",
        "displayName": "Street Address 2"
      },
      "city": {
        "type": "text",
        "currentValue": "",
        "displayName": "City",
        "required": true
      },
      "state": {
        "inline": true,
        "type": "dropdown",
        "currentValue": "",
        "displayName": "State",
        "required": true,
        "options": [
          "CA",
          "NH"
        ]
      },
      "zipcode": {
        "inline": true,
        "type": "text",
        "currentValue": "",
        "displayName": "Zipcode",
        "required": true
      },
      "companyWebsite": {
        "type": "text",
        "currentValue": "",
        "displayName": "Company Website",
        "required": true
      }
    }
  }

Secondary file:
{
	"general": {
		"company": "XYZ",
		"streetAddress1": "ABC street",
		"streetAddress2": "",
		"city": "SFO",
		"state": "CA",
		"zipcode": "12345",
		"companyWebsite": "https://example.com"
	}

OK so i tried something like, but it always fails with the below error? Any ideas how to fix this?
I basically passed the pointer of the old struct, new struct as existingEntity & newEntity

Error: panic: reflect: call of reflect.Value.FieldByName on ptr Value

entityType := reflect.TypeOf(existingEntity).Elem()
	for i := 0; i < entityType.NumField(); i++ {
		value := entityType.Field(i)
		value1 := entityType.Field(i).Name
		fmt.Println(value1)
		//tag := value.Tag
	templateField := reflect.ValueOf(existingEntity).Elem().Field(i)
	answerField := reflect.ValueOf(newEntity).FieldByName(value.Name)

	fmt.Println("the old field looks like ", oldField)
	fmt.Println("the new field looks like ", newField)
111

error: answerField := reflect.ValueOf(newEntity).FieldByName(value.Name)

Value.FieldByName

FieldByName returns the struct field with the given name. It returns the zero Value if no field was found. It panics if v’s Kind is not struct.


your err is Error: panic: reflect: call of reflect.Value.FieldByName on ptr Value, Value type is Ptr, Value type not is struct to panic.

@Contra_Boy is this what you’re looking for: https://play.golang.org/p/9YYXCLmSlOL

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.