Jérôme
Jérôme

Reputation: 1080

How to convert string from interface to []string in golang?

I'm parsing a JSON object which contains an array of strings :

var ii interface{}
json := "{\"aString\": [\"aaa_111\", \"bbb_222\"], \"whatever\":\"ccc\"}"

err := json.Unmarshal([]byte(json), &ii)
if err != nil {
    log.Fatal(err)
}
data := ii.(map[string]interface{})
fmt.Println(data["aString"]) // outputs: ["aaa_111" "bbb_222"]

I tried to convert data["aString"] to []string to be able to loop over it, but it fails :

 test := []string(data["aString"]).([]string)
 fmt.Println(test) // panic -> interface conversion: 
                   //          interface is string, not []string

How can I convert data["aString"] ?


edit:

I didn't express myself properly. If I print data, I have such map :

map[aString:["BBB-222","AAA-111"] whatever:ccc]

I want to loop over aString (to manipule each array entry). But I can't find how, because aString is type interface {} :

for i, v := range aString { // <-- fails
     // ...
     fmt.Println(i, v)
}

That's why I want to convert aString. I don't want to convert a string which looks like an array to an array.

Upvotes: 20

Views: 43407

Answers (4)

noob
noob

Reputation: 1

I'm solving that by just Marshall and Unmarshall:

type Paragraph struct {
    Paragraph_id          string    `json:"paragraph_id"`
    Parent_document_id    string    `json:"parent_document_id"`
    Page_in_document      int       `json:"page_in_document"`
    Text                  string    `json:"text"`
    Previous_paragraph_id string    `json:"previous_paragraph_id"`
    Parent_paragraph_id   string    `json:"parent_paragraph_id"`
    Child_paragraph_ids   []string  `json:"child_paragraph_ids"`
    Next_paragraph_id     string    `json:"next_paragraph_id"`
    Summary               string    `json:"summary"`
    Vector                []float64 `json:"vector"`
    Definitions           []string  `json:"definitions"`
    Keywords              []string  `json:"keywords"`
    IsLeaf                bool      `json:"leaf"`
}

_, err := session.ExecuteRead(db_ctx, func(transaction neo4j.ManagedTransaction) (any, error) {
        result, _:= transaction.Run(db_ctx,
            "MATCH (paragraph:Paragraph) RETURN paragraph",
            map[string]any{},
        )

    paragraphs = []Paragraph{}

    for result.Next(db_ctx) {
            record := result.Record()       
            para, _ := record.Get("paragraph")
            properties := para.(neo4j.Node).GetProperties()
            bytes, _ := json.Marshal(properties)

            var paragraph knowledge_structs.Paragraph
            json.Unmarshal(bytes, &paragraph)

            paragraphs = append(paragraphs, paragraph)
}

Not sure how efficient it is ;)

Upvotes: 0

Zombo
Zombo

Reputation: 1

For another approach, you can use a struct instead:

package main

import (
   "encoding/json"
   "fmt"
)

func main() {
   s := []byte(`{"aString": ["aaa_111", "bbb_222"], "whatever":"ccc"}`)
   var t struct {
      Astring []string
      Whatever string
   }
   json.Unmarshal(s, &t)
   fmt.Printf("%+v\n", t) // {Astring:[aaa_111 bbb_222] Whatever:ccc}
}

Upvotes: 0

evanmcdonnal
evanmcdonnal

Reputation: 48086

I recommend you move away from this implementation in general. Your json may vary but you can easily use objects and avoid all this type unsafe nonsense.

Anyway, that conversion doesn't work because the types inside the slice are not string, they're also interface{}. You have to iterate the collection then do a type assertion on each item like so:

aInterface := data["aString"].([]interface{})
aString := make([]string, len(aInterface))
for i, v := range aInterface {
    aString[i] = v.(string)
}

Upvotes: 48

Apin
Apin

Reputation: 2668

Is it what you need?

package main

import (
    "fmt"
    "encoding/json"
)

func main() {
    js := "{\"aString\": [\"aaa_111\", \"bbb_222\"], \"whatever\":\"ccc\"}"
    a := make(map[string]interface{})
    json.Unmarshal([]byte(js), &a)
    for _, v := range a["aString"].([]interface{}) {
        str := v.(string)
        fmt.Println(str)
    }
}

Check on Go Playground

Upvotes: 5

Related Questions