esnible
esnible

Reputation: 360

DeepEqual: Why does an unmarshalled map return DeepEqual() results differently than a seemingly identical literal

I don't understand how to compare unmarshalled JSON. Example:

package main

import (
    "fmt"
    "reflect"
    "encoding/json"
)

func main() {
    a := map[string]interface{} {"foo": 1, "bar": 2}
    b := map[string]interface{} {"bar": 2, "foo": 1}
    fmt.Printf("Literal B is %v, DeepEqual is %v\n", b, reflect.DeepEqual(a, b))

    err := json.Unmarshal([]byte(`{"bar": 2, "foo": 1}`), &b)
    if err != nil {
        panic("Could not unmarshal")
    }
    fmt.Printf("Umarshalled B is %v, DeepEqual is %v\n", b, reflect.DeepEqual(a, b))
}

prints

Literal B is map[bar:2 foo:1], DeepEqual is true

Umarshalled B is map[bar:2 foo:1], DeepEqual is false

What is different about the B initialized from a literal and B after JSON is unmarshalled upon it?

Upvotes: 2

Views: 371

Answers (1)

Ainar-G
Ainar-G

Reputation: 36199

This answers your question:

fmt.Printf("%T\n", b["foo"]) // Prints "float64" after unmarshaling.

JSON numbers are 64-bit floating point numbers, while your original map values were integers. From the docs:

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: 4

Related Questions