Home  >  Article  >  Backend Development  >  Why Does JSON Unmarshal Return a Map Instead of a Struct in Go When Working with Interfaces?

Why Does JSON Unmarshal Return a Map Instead of a Struct in Go When Working with Interfaces?

Barbara Streisand
Barbara StreisandOriginal
2024-10-25 09:26:02605browse

Why Does JSON Unmarshal Return a Map Instead of a Struct in Go When Working with Interfaces?

Mystery Behind JSON Unmarshal Returning a Map Instead of the Intended Struct

JSON unmarshaling in Go can pose challenges when dealing with interfaces and structs. Developers may encounter situations where the unmarshal process yields a map instead of the expected struct, as is the case in the given snippet:

<code class="go">import "encoding/json"
import "fmt"
import "reflect"

func main() {
    type Ping struct {
        ID int `json:"id"`
    }
    var ping interface{} = Ping{}
    if err := json.Unmarshal([]byte(`{"id":42}`), &ping); err != nil {
        panic(err)
    }
    fmt.Println("Unexpected:", ping) // Result: map[id:42]
}</code>

The underlying reason for this behavior lies in the abstract nature of interfaces. When JSON unmarshaling is performed on an interface, the result is a map representing the underlying type's fields. In the example above, the interface Ping holds a map with a single key-value pair: {"id":42}.

To rectify this issue and obtain the desired struct, it is crucial to pass a pointer to the specific struct type:

<code class="go">type Ping struct {
    ID int `json:"id"`
}
func main() {
    var ping Ping
    if err := json.Unmarshal([]byte(`{"id":42}`), &ping); err != nil {
        panic(err)
    }
    fmt.Println("Success:", ping) // Result: {42}
}</code>

By passing the pointer to Ping, the JSON unmarshal process is directed to create an instance of the struct and populate its fields rather than creating a map.

Alternatively, if a pointer to the concrete struct is unavailable, you can employ reflection to dynamically create the pointer and subsequently assign its value to the interface:

<code class="go">import "reflect"

func main() {
    var ping interface{} = Ping{}
    nptr := reflect.New(reflect.TypeOf(ping))
    if err := json.Unmarshal([]byte(`{"id":42}`), nptr.Interface()); err != nil {
        panic(err)
    }
    ping = nptr.Elem().Interface()
    fmt.Println("Reflect-Based:", ping) // Result: {42}
}</code>

The above is the detailed content of Why Does JSON Unmarshal Return a Map Instead of a Struct in Go When Working with Interfaces?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn