Programming
Interface Unmarshaling
Type Assertion
Coding Methods
Data Handling

Unmarshaling Into an Interface{} and Then Performing Type Assertion

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Go, unmarshaling JSON into interface{} or any is a way to accept data with a shape you do not know in advance. Once you do that, you must inspect the concrete types that encoding/json produced and use type assertions carefully.

What json.Unmarshal Produces

When JSON is decoded into interface{}, Go uses a small set of default concrete types:

  • JSON object becomes map[string]any
  • JSON array becomes []any
  • JSON string becomes string
  • JSON boolean becomes bool
  • JSON number becomes float64
  • JSON null becomes nil

That mapping explains why later assertions succeed or fail.

go
1package main
2
3import (
4    "encoding/json"
5    "fmt"
6)
7
8func main() {
9    var data any
10    raw := []byte(`{"name":"John","age":30}`)
11
12    if err := json.Unmarshal(raw, &data); err != nil {
13        panic(err)
14    }
15
16    fmt.Printf("%T\n", data)
17}

The printed type will be map[string]interface {}.

Safe Type Assertion

After decoding, use the two-result form of a type assertion so your code does not panic if the data shape is different from what you expected.

go
1m, ok := data.(map[string]any)
2if !ok {
3    panic("expected JSON object")
4}
5
6name, _ := m["name"].(string)
7age, _ := m["age"].(float64)
8
9fmt.Println(name, age)

The ok result is what makes the assertion safe.

Type Switches Help with Mixed Shapes

When the decoded value might be one of several shapes, a type switch is often cleaner than repeated individual assertions.

go
1var data any
2raw := []byte(`["hello", {"count": 2}, true]`)
3json.Unmarshal(raw, &data)
4
5for _, item := range data.([]any) {
6    switch v := item.(type) {
7    case string:
8        fmt.Println("string:", v)
9    case map[string]any:
10        fmt.Println("object:", v)
11    case bool:
12        fmt.Println("bool:", v)
13    default:
14        fmt.Println("unknown:", v)
15    }
16}

This is easier to read when the schema is genuinely loose.

Numbers Surprise People

One of the biggest surprises is that numbers become float64 when you decode into interface{}.

That means code like this fails:

go
_, ok := m["age"].(int)

because the value is actually float64, not int.

If numeric precision matters, you may want to move away from interface{} decoding or use a decoder with UseNumber.

Prefer Structs When the Shape Is Known

If the JSON has a stable schema, decoding into a struct is usually the better design.

go
1type User struct {
2    Name string `json:"name"`
3    Age  int    `json:"age"`
4}
5
6var user User
7err := json.Unmarshal([]byte(`{"name":"John","age":30}`), &user)
8fmt.Println(user.Name, user.Age, err)

This avoids most type assertions and gives you compile-time structure.

When interface{} Is Actually Appropriate

Decoding into interface{} makes sense when:

  • the JSON shape is truly dynamic
  • you are writing generic tooling
  • you need to inspect arbitrary payloads before deciding what they are

If the schema is known ahead of time, interface{} usually creates extra work rather than flexibility.

Common Pitfalls

Assuming JSON numbers become int is a classic mistake. They become float64 by default.

Using single-result assertions can panic when the input shape changes unexpectedly.

Decoding into interface{} even when a concrete struct would be simpler often makes the code harder to read and test.

Forgetting that arrays become []any and objects become map[string]any leads to failed assertions in nested data.

Summary

  • Unmarshaling into interface{} is useful for dynamic JSON, not for stable schemas.
  • 'encoding/json maps JSON values to default Go types such as map[string]any, []any, and float64.'
  • Use safe type assertions or type switches after decoding.
  • If the schema is known, prefer decoding into a concrete struct.
  • The most common source of confusion is number handling, not the interface itself.

Course illustration
Course illustration

All Rights Reserved.