문자열에서 float64로 유형 변환을 사용하여 JSON을 디코딩하는 방법


86

다음과 같은 float 숫자로 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}

유형 변환으로 JSON 문자열을 디코딩하는 방법을 알고 싶습니다.

답변:


170

대답은 훨씬 덜 복잡합니다. JSON interpeter에게 문자열로 인코딩 된 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
앞에 쉼표 json:",string"가 있어야합니다.이 쉼표 없이는 작동하지 않습니다.
Darrrrrren 2014

1
@dustin 다른 방법으로 수행하는 방법에 대한 아이디어가 있습니까? JSON 번호를 문자열로 변환 하시겠습니까? 예 "N": 1234를 들어 N: "1234"?
Kamil Dziedzic

정말 대단합니다. 슬라이스에서 작동하지 않는 것을 제외하고는. 누구든지 [] int를 위해 이것을 수행하는 방법을 알고 있습니까? 단순히 "문자열"플래그를 생성합니다 추가 : "수 INT의 이동 값에하지 정렬 화 문자열"( play.golang.org/p/aFWSH4lUxv )
달리 보르 Filus

@KamilDziedzic 질문에 대한 해결책을 얻었습니까?
maverick

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

문자열을 [] byte :로 변환하지 마십시오 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

3

따옴표로 값을 전달하면 문자열처럼 보입니다. 로 변경 "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

1
@yanunon 예,에 map[string]interface{}대한 유형의 맵을 사용하고이를 Unmarshal구조체로 구문 분석 할 수 있습니다.
Mostafa 2012

@yanunon 또는 실제 유연성 을 원하면 Unmarshal기본 Unmarshal을 a로 호출 map[string]interface{}하지만 reflectstrconv패키지를 사용 하여 구문 분석을 수행하는 자체를 작성할 수 있습니다 .
Mostafa
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.