Keeto
Keeto

Reputation: 4198

Unmarshaling a JSON integer to an empty interface results in wrong type assertion

I have this code. I expect the interface to be type asserted to int. However, the type of the interface is float64 instead. Can anyone explain why this is happening? And what are the best ways to circumvent it.

package main

import (
    "fmt"
    "encoding/json"
)

type obj struct {
    X interface{}
}

func main() {
    var x int
    x = 5
    o := &obj {
        X: x,
    }
    b, _ := json.Marshal(o)
    var newObj obj
    json.Unmarshal(b, &newObj)
    if _, ok := newObj.X.(int); ok {
        fmt.Println("X is an int")
    } else if _, ok := newObj.X.(float64); ok {
        fmt.Println("X is a float64")
    } else {
        fmt.Println("This does not make any sense")
    }
}

This code prints "X is a float64". You can run the code there https://play.golang.org/p/9L9unW8l3n

Upvotes: 1

Views: 1985

Answers (1)

Benjamin Kadish
Benjamin Kadish

Reputation: 1500

Numbers are encoded as "Json numbers" Unmarshal decodes Json numbers as floats. From the docs:

Marshal

Floating point, integer, and Number values encode as JSON numbers.

Unmarshal

To unmarshal JSON into an interface value, Unmarshal stores one of these in the interface value:

bool, for JSON booleans float64, for JSON numbers string, for JSON strings []interface{}, for JSON arrays map[string]interface{}, for JSON objects nil for JSON null

Upvotes: 5

Related Questions