-1

I am looping over a slice in Go that is made up of a struct I made called Product.

I want to turn this slice into a map so that the Product Id is the key and the Product is the value.

Here is the struct I created.

type Product struct {
    productID      int    `json:"prodId"`
    Manufacturer   string `json:"manufacturer"`
    PricePerUnit   string `json:"ppu"`
    Sku            string `json:"sku"`
    Upc            string `json:"upc"`
    QuantityOnHand int    `json:"qoh"`
    ProductName    string `json:"prodName"`
}

and here is the function I created...

func loadProductMap() (map[int]Product, error) {
    fileName := "products.json"
    _, err := os.Stat(fileName) //os package with the Stat method checks to see if the file exists
    if os.IsNotExist(err) {
        return nil, fmt.Errorf("file [%s] does not exist", fileName)
    }

    file, _ := ioutil.ReadFile(fileName)             //reads the file and returns a file and an error; not concerned with the error
    productList := make([]Product, 0)                //initialize a slice of type Product named productList, length is zero
    err = json.Unmarshal([]byte(file), &productList) // unmarshal/decode the json file and map it into the productList slice
    if err != nil {
        log.Fatal(err)
    }
    prodMap := make(map[int]Product) //initialize another variable called prodMap and make a map with the map key being an integer and the value being of type Product
    fmt.Println(len(productList))
    for i := 0; i < len(productList); i++ { //loop over the productList slice
        prodMap[productList[i].productID] = productList[i] //the productMap's key will be the productList product's ID at i and it's value will be the actual product (name, manufacturer, cost, etc) at productList[i]
        fmt.Println(prodMap)
    }
    fmt.Println(prodMap)
    return prodMap, nil
}

There's a lot more code, but all of it works correctly except for the for loop. When I print out the prod map in the for loop it does individually go over every single item in the productList (190 items) but then it will only return the one item - the last one. Am I supposed to be appending each iteration to the map somehow? I was coding alongside the video tutorial and have the source file from the tutorial video and cannot find anything wrong with my code compared to theirs....

maura
  • 23
  • 2
  • 1
    Welcome to StackOverflow and Go! @BurakSerdar's answer is correct, I just wanted to point out that for more context you may want to read this discussion: https://stackoverflow.com/questions/11126793/json-and-dealing-with-unexported-fields – Eli Bendersky Feb 13 '21 at 22:09
  • Does this answer your question? [JSON and dealing with unexported fields](https://stackoverflow.com/questions/11126793/json-and-dealing-with-unexported-fields) – colm.anseo Feb 14 '21 at 05:17

2 Answers2

3

The struct field productId is not exported, so json.Unmarshal cannot set it, and all your product Ids are zero. Export it: ProductId, and it should work.

Burak Serdar
  • 37,605
  • 3
  • 27
  • 46
0

Your json.Unmarshal will not be able to access your struct field productID. This is because the productID is an unexpected field, which means it is like a private variable of the struct.

You can change your field productID -> ProductID, which makes your struct field exported now(since the variable name starts with Uppercase it will be like public variable in other language). Your json.Unmarshal will now be able to happily access the ProductID