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

Barbara Streisand
Release: 2024-10-25 09:26:02
Original
619 people have browsed it

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>
Copy after login

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>
Copy after login

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>
Copy after login

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!

source:php.cn
Statement of this Website
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
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!