jsongoreflect

Extract value from an array in a Json


I'm trying to get "boots" value

My func main

varjson:=`{
  "identifier": "1",
  "name": "dumbname",
  "person": {
    "items": null,
    "inventory": [
      {
        "T-shirt": "black",
        "Backpack": {
          "BigPocket": {
            "spell": "healing",
            "boots": "speed",
            "shampoo": "Head & Shoulders"
          }
        }
      }
    ],
    "Pockets": null
  }
}`

var res map[string]interface{}

json.Unmarshal([]byte(varjson), &res)

test(res) 

test function

    func test(t interface{}) {
      switch reflect.TypeOf(t).Kind() {
       case reflect.Slice:
        s := reflect.ValueOf(t)
    for i := 0; i < s.Len(); i++ {
        fmt.Println(s.Index(i))
        }
      }
    }

But when I compile I get nothing If is there another way to get the "boot" value in the Json?


Solution

  • Assuming you can use types, based on your comment (thankfully cause totally agree with colm, trying to reflect the structure is rough.

    Once you have a type its super easy to navigate.

    specifically fmt.Println(res.Person.Inventory[0].Backpack.BigPocket.Boots) would net you the boots value. Bearing in mind that Inventory is a slice so you probably need to iterate over that, whereas here I have directly accessed it, which will be bad if Inventory is empty or there are other elements.

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    type AutoGenerated struct {
        Identifier string `json:"identifier"`
        Name       string `json:"name"`
        Person     struct {
            Items     interface{} `json:"items"`
            Inventory []struct {
                TShirt   string `json:"T-shirt"`
                Backpack struct {
                    BigPocket struct {
                        Spell   string `json:"spell"`
                        Boots   string `json:"boots"`
                        Shampoo string `json:"shampoo"`
                    } `json:"BigPocket"`
                } `json:"Backpack"`
            } `json:"inventory"`
            Pockets interface{} `json:"Pockets"`
        } `json:"person"`
    }
    
    func main() {
        varjson := `{
      "identifier": "1",
      "name": "dumbname",
      "person": {
        "items": null,
        "inventory": [
          {
            "T-shirt": "black",
            "Backpack": {
              "BigPocket": {
                "spell": "healing",
                "boots": "speed",
                "shampoo": "Head & Shoulders"
              }
            }
          }
        ],
        "Pockets": null
      }
    }`
    
        var res AutoGenerated
        json.Unmarshal([]byte(varjson), &res)
        
        fmt.Println(res.Person.Inventory[0].Backpack.BigPocket.Boots)
    }
    

    In your original, whats wrong is your switch statement only covers a slice, but the initial object is a map. So your switch is not finding a match initially