总是将JSON解组为特定类型(字符串)

总是将JSON解组为特定类型(字符串),json,go,unmarshalling,Json,Go,Unmarshalling,我有一些JSON,第一个元素可以是数字或字符串。我总是希望能够将其存储为字符串值,但相反,我得到了一个崩溃,因为它读取的结果与数字类型一样正确 我试图强制将解组作为字符串,但没有成功 string `json:",string"` 我正在遵循这一点,这似乎很符合我的数据 如何始终使[0]处的此元素始终读取并保存为字符串 下面是代码和操场 您可以创建一个通用接收器,即接口类型,然后执行类型断言: package main import ( "encoding/json" "f

我有一些JSON,第一个元素可以是数字或字符串。我总是希望能够将其存储为字符串值,但相反,我得到了一个崩溃,因为它读取的结果与数字类型一样正确

我试图强制将解组作为字符串,但没有成功

string `json:",string"`
我正在遵循这一点,这似乎很符合我的数据

如何始终使[0]处的此元素始终读取并保存为字符串

下面是代码和操场


您可以创建一个通用接收器,即接口类型,然后执行类型断言:

package main

import (
    "encoding/json"
    "fmt"
)

type RawMessage struct {
    UnknownType interface{} `json:"unknown_type"`
}

const inputString = `{"unknown_type" : "a"}`

const inputFloat = `{"unknown_type" : 123}` // Note: Unmarshals into a float64 by default!!!

func main() {

    var n RawMessage
    if err := json.Unmarshal([]byte(inputFloat), &n); err != nil {
        println(err.Error())
    }

    switch v := n.UnknownType.(type) {
    case string:
        fmt.Printf("Received a string: %v", v)
    case float64:
        fmt.Printf("Received a number: %v", v)
    default:
        fmt.Printf("Unknown type: %v", v)
    }
}

如果解决了此问题,请尝试此操作,因为未定义用户输入,请创建一个通用接口

interface{} `json:",string"`
包干管

import "fmt"
import "log"
import "encoding/json"

const inputWorking = `
["AAAAAA", {"testcode" : "Sss"}, 66666666]
`

const inputBroken = `
[111111, {"testcode" : "Sss"}, 66666666]
`

type RawMessage struct {
    AlwaysString        interface{} `json:",string"`
    ClientData    ClientData
    ReceptionTime int
}

type ClientData struct {
    testcode string
}

func main() {

    var n RawMessage
    if err := json.Unmarshal([]byte(inputWorking), &n); err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%#v\n", n)

    var o RawMessage
    if err := json.Unmarshal([]byte(inputBroken), &o); err != nil {
        log.Fatal(err)
    }

我也遇到了同样的问题,到目前为止,我发现最好的方法是使用自定义解组器从字符串生成类型:

package main

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

// Stringish exists because api send back integers unquoted even if underlying type is string
type StringIsh string

func (f *StringIsh) UnmarshalJSON(data []byte) error {

    var receiver string
    if len(data) == 0 {
        return nil
    }
    if data[0] != '"' {
        quoted := strconv.Quote(string(data))
        data = []byte(quoted)
    }

    if err := json.Unmarshal(data, &receiver); err != nil {
        return err
    }
    *f = StringIsh(receiver)
    return nil

}

type Test struct {
    Foo StringIsh
}

func main() {
    dest := &Test{}
    _ = json.Unmarshal([]byte(`{"foo": "bar"}`), &dest)
    fmt.Println(dest)

    dest = &Test{}
    _ = json.Unmarshal([]byte(`{"foo": 123}`), &dest)
    fmt.Println(dest)
}

你自己试试吧

啊,当然可以!所以有点像。。。每当我读取这个值时,我都会确保检查它?@LeeArmstrong,是的-你把它放到接口{}中,然后断言它是字符串还是数字。请记住,Go不会在接收时区分整型和浮点型,它只会为所有内容提供浮点64。因此,如果需要的话,您可能还需要将其转换为int。这与上面的方法没有什么不同,并且不会另存为字符串
package main

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

// Stringish exists because api send back integers unquoted even if underlying type is string
type StringIsh string

func (f *StringIsh) UnmarshalJSON(data []byte) error {

    var receiver string
    if len(data) == 0 {
        return nil
    }
    if data[0] != '"' {
        quoted := strconv.Quote(string(data))
        data = []byte(quoted)
    }

    if err := json.Unmarshal(data, &receiver); err != nil {
        return err
    }
    *f = StringIsh(receiver)
    return nil

}

type Test struct {
    Foo StringIsh
}

func main() {
    dest := &Test{}
    _ = json.Unmarshal([]byte(`{"foo": "bar"}`), &dest)
    fmt.Println(dest)

    dest = &Test{}
    _ = json.Unmarshal([]byte(`{"foo": 123}`), &dest)
    fmt.Println(dest)
}