简体   繁体   中英

Go: Converting JSON string to map[string]interface{}

I'm trying to create a JSON representation within Go using a map[string]interface{} type. I'm dealing with JSON strings and I'm having a hard time figuring out how to avoid the JSON unmarshaler to automatically deal with numbers as float64s. As a result the following error occurs.

Ex. "{ 'a' : 9223372036854775807}" should be map[string]interface{} = [a 9223372036854775807 but in reality it is map[string]interface{} = [a 9.2233720368547758088E18]

I searched how structs can be used to avoid this by using json.Number but I'd really prefer using the map type designated above.

The go json.Unmarshal(...) function automatically uses float64 for JSON numbers. If you want to unmarshal numbers into a different type then you'll have to use a custom type with a custom unmarshaler. There is no way to force the unmarshaler to deserialize custom values into a generic map.

For example, here's how you could parse values of the "a" property as a big.Int .

package main

import (
  "encoding/json"
  "fmt"
  "math/big"
)

type MyDoc struct {
  A BigA `json:"a"`
}

type BigA struct{ *big.Int }

func (a BigA) UnmarshalJSON(bs []byte) error {
  _, ok := a.SetString(string(bs), 10)
  if !ok {
    return fmt.Errorf("invalid integer %s", bs)
  }
  return nil
}

func main() {
  jsonstr := `{"a":9223372036854775807}`
  mydoc := MyDoc{A: BigA{new(big.Int)}}

  err := json.Unmarshal([]byte(jsonstr), &mydoc)
  if err != nil {
    panic(err)
  }

  fmt.Printf("OK: mydoc=%#v\n", mydoc)
  // OK: mydoc=main.MyDoc{A:9223372036854775807}
}
func jsonToMap(jsonStr string) map[string]interface{} {
    result := make(map[string]interface{})
    json.Unmarshal([]byte(jsonStr), &result)
    return result
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM