如何在Golang中将类型从字符串转换为float64解码JSON?


83

我需要使用浮点数解码JSON字符串,例如:

{"name":"Galaxy Nexus", "price":"3460.00"}

我使用下面的Golang代码:

package main

import (
    "encoding/json"
    "fmt"
)

type Product struct {
    Name  string
    Price float64
}

func main() {
    s := `{"name":"Galaxy Nexus", "price":"3460.00"}`
    var pro Product
    err := json.Unmarshal([]byte(s), &pro)
    if err == nil {
        fmt.Printf("%+v\n", pro)
    } else {
        fmt.Println(err)
        fmt.Printf("%+v\n", pro)
    }
}

当我运行它时,得到的结果是:

json: cannot unmarshal string into Go value of type float64
{Name:Galaxy Nexus Price:0}

我想知道如何使用convert类型解码JSON字符串。

Answers:


164

答案相当简单。只需添加告诉JSON交互器,它就是一个用float64编码的字符串,string(请注意,我只更改了Price定义):

package main

import (
    "encoding/json"
    "fmt"
)

type Product struct {
    Name  string
    Price float64 `json:",string"`
}

func main() {
    s := `{"name":"Galaxy Nexus", "price":"3460.00"}`
    var pro Product
    err := json.Unmarshal([]byte(s), &pro)
    if err == nil {
        fmt.Printf("%+v\n", pro)
    } else {
        fmt.Println(err)
        fmt.Printf("%+v\n", pro)
    }
}

谢谢!我认为这是解决我的问题的最佳方法。您能告诉我有关“,string”用法的官方文件在哪里吗?
yanunon'3

3
请注意,必须使用逗号前面的逗号json:",string"-如果没有逗号,它将不起作用。
Darrrrrren 2014年

1
@dustin任何想法如何做其他方式?转换json编号转为字符串?例如"N": 1234N: "1234"
卡米尔·吉兹奇

真的很棒 除非它不适用于切片。有谁知道如何为[] int执行此操作?‘不能解组字符串转换成int的去价值’(:只需添加“字符串”标志产生play.golang.org/p/aFWSH4lUxv
DALIBOR Filus

@KamilDziedzic您是否获得了查询的解决方案?
特立独行

12

只是让您知道可以不Unmarshal使用而使用json.decode。这是围棋场

package main

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

type Product struct {
    Name  string `json:"name"`
    Price float64 `json:"price,string"`
}

func main() {
    s := `{"name":"Galaxy Nexus","price":"3460.00"}`
    var pro Product
    err := json.NewDecoder(strings.NewReader(s)).Decode(&pro)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(pro)
}

4

用引号引起来的值使它看起来像字符串。更改"price":"3460.00""price":3460.00,一切正常。

如果您不能删除引号,则必须使用strconv.ParseFloat以下命令自己解析:

package main

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

type Product struct {
    Name       string
    Price      string
    PriceFloat float64
}

func main() {
    s := `{"name":"Galaxy Nexus", "price":"3460.00"}`
    var pro Product
    err := json.Unmarshal([]byte(s), &pro)
    if err == nil {
        pro.PriceFloat, err = strconv.ParseFloat(pro.Price, 64)
        if err != nil { fmt.Println(err) }
        fmt.Printf("%+v\n", pro)
    } else {
        fmt.Println(err)
        fmt.Printf("%+v\n", pro)
    }
}

有没有一种方法不更改'Product'结构并实现解码功能或接口以解析浮点字符串?
yanunon'2

1
@yanunon是的,你可以使用地图类型map[string]interface{}Unmarshal,并解析到你的结构。
Mostafa

@yanunon或者,如果你想真正的灵活性,你可以写你自己的Unmarshal,它调用默认Unmarshal使用 map[string]interface{},但使用reflectstrconv包装做了解析。
Mostafa

3

避免将字符串转换为[]字节:b := []byte(s)。它分配一个新的内存空间并将整个内容复制到其中。

strings.NewReader界面比较好。以下是来自godoc的代码:

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "strings"
)

func main() {
    const jsonStream = `
    {"Name": "Ed", "Text": "Knock knock."}
    {"Name": "Sam", "Text": "Who's there?"}
    {"Name": "Ed", "Text": "Go fmt."}
    {"Name": "Sam", "Text": "Go fmt who?"}
    {"Name": "Ed", "Text": "Go fmt yourself!"}
`
    type Message struct {
        Name, Text string
    }
    dec := json.NewDecoder(strings.NewReader(jsonStream))
    for {
        var m Message
        if err := dec.Decode(&m); err == io.EOF {
            break
        } else if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("%s: %s\n", m.Name, m.Text)
    }
}

我引用了您的回答,这很有意义。我添加了吗?参见stackoverflow.com/a/62740786/12817546
Tom L
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.