适配java fastjson包解析Map的Key类型int的json串

首先说明json是不支持{"Bar":"test","M":{1:"a",2:"b"}}key是int的json字符串,官方encoding/json包也不解析这类json串。为什么还要解析这样的josn串呢。java的fastjson对Map解析生产1:"a",2:"b"的非标准json串。接下来就来实现解析这类非标准的json串吧。

json接口

encoding/json包中定义了json.Unmarshalerjson.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目录下)

1
ffjson foo.go

生成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串是不提倡的,这里给出了其它系统或语言出现这种情况的处理方法。