Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unmarshal generic json in Go

Tags:

json

go

I'm a new Go programmer (From Java) and I would like to reproduce a generic way which is esay to use in Java.

I want to create some function which allow me to do an Unmarshal on a JSON string in order to avoid code duplicity.

This is my current code which is not working :

type myStruct1 struct {
    id string
    name string
}

func (obj myStruct1) toString() string {
    var result bytes.Buffer
    result.WriteString("id : ")
    result.WriteString(obj.id)
    result.WriteString("\n")
    result.WriteString("name : ")
    result.WriteString(obj.name)

    return result.String()
}

func main() {

    content := `{id:"id1",name="myName"}`
    object := myStruct1{}
    parseJSON(content, object)

    fmt.Println(object.toString()) 
}

func parseJSON(content string, object interface{}) {
    var parsed interface{}
    json.Unmarshal([]byte(content), &parsed)
}

This code, on run, returns me this :

id : 
name : 

Do you have any idea ?

Thanks

like image 279
Jérémy Bricout Avatar asked Mar 17 '16 13:03

Jérémy Bricout


People also ask

What is JSON Unmarshal in Golang?

Unmarshaling: Converting JSON to Go objects. In the Go environment, the JSON document decoding process is called unmarshaling. We can use the Unmarshal function to convert JSON to Go objects. The Unmarshal function comes with the following syntax. func Unmarshal(data []byte, v interface{}) error.

How does JSON Unmarshal work Golang?

To unmarshal a JSON array into a slice, Unmarshal resets the slice length to zero and then appends each element to the slice. As a special case, to unmarshal an empty JSON array into a slice, Unmarshal replaces the slice with a new empty slice.

How do you Unmarshal in Go?

Unmarshal is the contrary of marshal. It allows you to convert byte data into the original data structure. In go, unmarshaling is handled by the json. Unmarshal() method.

How do I declare JSON in Golang?

Go encode to JSONWe declare the User struct. We create the struct instance. We encode the u1 struct into JSON with Marshal . Since json_data is a byte array, we convert it to a string with the string function.


2 Answers

The issue is you want to write to a generic type? You probably want a string map. This works with BSON anyways:

var anyJson map[string]interface{}
json.Unmarshal(bytes, &anyJson)

You'll be able to access the fields like so:

anyJson["id"].(string)

Don't forget to type assert your values, and they must be the correct type or they'll panic. (You can read more about type assertions on the golang site)

like image 78
user161778 Avatar answered Oct 15 '22 12:10

user161778


To parse "generic JSON" when you have no idea what schema it has:

    var parsed interface{}
    err := json.Unmarshal(jsonText, &parsed)

The returned interface{} in parsed will be a map[string]interface{} or []interface{}.

You can test the type and react accordingly.

import (
    "encoding/json"
    "fmt"
)

func test(jsonText []byte) {
    // parsing
    var parsed interface{}
    err := json.Unmarshal(jsonText, &parsed)
    if err != nil {
        panic(err) // malformed input
    }

    // type-specific logic
    switch val := parsed.(type) {
    case map[string]interface{}:
        fmt.Printf("id:%s name:%s\n", val["id"], val["name"])
    case []interface{}:
        fmt.Printf("list of %d items\n", len(val))
    default:
        panic(fmt.Errorf("type %T unexpected", parsed))
    }
}
like image 31
jws Avatar answered Oct 15 '22 13:10

jws