首先说明json是不支持{"Bar":"test","M":{1:"a",2:"b"}}
key是int的json字符串,官方encoding/json
包也不解析这类json串。为什么还要解析这样的josn串呢。java的fastjson对Map<Int, String>解析生产1:"a",2:"b"
的非标准json串。接下来就来实现解析这类非标准的json串吧。
json接口
encoding/json
包中定义了json.Unmarshaler
与json.Marshaler
接口来解析json。对结构体实现这两个接口,一切都搞定了。
1 2 3 4 5 6 7
| type Unmarshaler interface { UnmarshalJSON([]byte) error }
type Marshaler interface { MarshalJSON() ([]byte, error) }
|
接口实现
我使用Golang ffjson第三方包,自己没有去实现此功能。这里说下思路,UnmarshalJSON接口实现中step解析key没有"
判断是否map[int]string类型,否则返回错误。
使用ffjosn
先给出示例代码
1 2 3 4 5 6
| package m
type Foo struct { Bar string M map[int]string }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package main
import ( "encoding/json" "fmt"
"github.com/gunsluo/go-example/ffjson/m" )
func main() { buf := []byte(`{"Bar":"test","M":{1:"a",2:"b"}}`) nf := new(m.Foo) err := json.Unmarshal(buf, nf) if err != nil { panic(err) }
fmt.Println("-->", nf) }
|
使用json包,报错panic: invalid character '1' looking for beginning of object key string
将json换成ffjson
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package main
import ( "fmt"
"github.com/gunsluo/go-example/ffjson/m" "github.com/pquerna/ffjson/ffjson" )
func main() { buf := []byte(`{"Bar":"test","M":{1:"a",2:"b"}}`) nf := new(m.Foo) err := ffjson.Unmarshal(buf, nf) if err != nil { panic(err) }
fmt.Println("-->", nf) }
|
直接执行代码会报相同的错误,ffjson检查到Foo没有实现ffjson.unmarshalFaster
或重写json.Unmarshaler
会使用json来代替解析。
需要执行命令(go get -u github.com/pquerna/ffjson
ffjson后会安装到GOPATH/bin目录下)
生成foo_ffjson.go文件,接着查看下该文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| func (mj *Foo) MarshalJSON() ([]byte, error) { var buf fflib.Buffer if mj == nil { buf.WriteString("null") return buf.Bytes(), nil } err := mj.MarshalJSONBuf(&buf) if err != nil { return nil, err } return buf.Bytes(), nil } func (mj *Foo) MarshalJSONBuf(buf fflib.EncodingBuffer) error { if mj == nil { buf.WriteString("null") return nil } var err error var obj []byte _ = obj _ = err buf.WriteString(`{"Bar":`) fflib.WriteJsonString(buf, string(mj.Bar)) /* Falling back. type=map[int]string kind=map */ buf.WriteString(`,"M":`) err = buf.Encode(mj.M) if err != nil { return err } buf.WriteByte('}') return nil }
|
上面截取了foo_ffjson.go的部分内容,它重写了MarshalJSON和MarshalJSONBuf方法。
最后执行代码,解析成功。
说明:非标准的json串是不提倡的,这里给出了其它系统或语言出现这种情况的处理方法。