mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
fix: task params nil params panic (#25697)
Co-authored-by: Qiu Jian <qiujian@yunionyun.com>
This commit is contained in:
6
go.mod
6
go.mod
@@ -12,6 +12,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.18.16
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.88.4
|
||||
github.com/aws/smithy-go v1.24.2
|
||||
github.com/beevik/etree v1.1.0
|
||||
github.com/benbjohnson/clock v1.0.0
|
||||
github.com/bitly/go-simplejson v0.5.0
|
||||
github.com/c-bata/go-prompt v0.2.4
|
||||
@@ -51,6 +52,7 @@ require (
|
||||
github.com/lestrrat-go/jwx v1.2.25
|
||||
github.com/lestrrat/go-jwx v0.0.0-20180221005942-b7d4802280ae
|
||||
github.com/libvirt/libvirt-go-xml v5.2.0+incompatible
|
||||
github.com/ma314smith/signedxml v0.0.0-20210628192057-abc5b481ae1c
|
||||
github.com/mark3labs/mcp-go v0.48.0
|
||||
github.com/mattn/go-sqlite3 v1.14.19
|
||||
github.com/mdlayher/arp v0.0.0-20190313224443-98a83c8a2717
|
||||
@@ -114,7 +116,7 @@ require (
|
||||
moul.io/http2curl/v2 v2.3.0
|
||||
yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260904120449-8aa2a5d6ba7a
|
||||
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005
|
||||
yunion.io/x/jsonutils v1.0.1-0.20260715075349-615cfb44ff7c
|
||||
yunion.io/x/jsonutils v1.0.1-0.20260916031541-8e0c8de6eb2e
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
yunion.io/x/ovsdb v0.0.0-20230306173834-f164f413a900
|
||||
yunion.io/x/pkg v1.10.4-0.20260722094907-0da70a14584f
|
||||
@@ -190,7 +192,6 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/basgys/goxml2json v1.1.1-0.20181031222924-996d9fc8d313 // indirect
|
||||
github.com/beevik/etree v1.1.0 // indirect
|
||||
github.com/benbjohnson/immutable v0.3.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.2.2 // indirect
|
||||
@@ -287,7 +288,6 @@ require (
|
||||
github.com/lestrrat-go/option v1.0.0 // indirect
|
||||
github.com/lestrrat/go-pdebug v0.0.0-20180220043741-569c97477ae8 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20220913051719-115f729f3c8c // indirect
|
||||
github.com/ma314smith/signedxml v0.0.0-20210628192057-abc5b481ae1c // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.11 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1782,8 +1782,8 @@ yunion.io/x/cloudmux v0.3.10-0-alpha.1.0.20260904120449-8aa2a5d6ba7a/go.mod h1:F
|
||||
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005 h1:3sWwcjGXGjG9mLBWa7AyLq+QSi0udTAx21pfVQRFMBE=
|
||||
yunion.io/x/executor v0.0.0-20260312022053-f538abd2b005/go.mod h1:Uxuou9WQIeJXNpy7t2fPLL0BYLvLiMvGQwY7Qc6aSws=
|
||||
yunion.io/x/jsonutils v0.0.0-20190625054549-a964e1e8a051/go.mod h1:4N0/RVzsYL3kH3WE/H1BjUQdFiWu50JGCFQuuy+Z634=
|
||||
yunion.io/x/jsonutils v1.0.1-0.20260715075349-615cfb44ff7c h1:FthZM1upg4/yF4vmYheo/J7a738sGPjWPKk5kY88sH0=
|
||||
yunion.io/x/jsonutils v1.0.1-0.20260715075349-615cfb44ff7c/go.mod h1:VK4Z93dgiKgAijcSqbMKmGaBMJuHulR16Hz4K015ZPo=
|
||||
yunion.io/x/jsonutils v1.0.1-0.20260916031541-8e0c8de6eb2e h1:0M7SVtySPc+zyHm4BqJ5XZQx2dDL2fwHccR/QZrbUMg=
|
||||
yunion.io/x/jsonutils v1.0.1-0.20260916031541-8e0c8de6eb2e/go.mod h1:VK4Z93dgiKgAijcSqbMKmGaBMJuHulR16Hz4K015ZPo=
|
||||
yunion.io/x/log v0.0.0-20190514041436-04ce53b17c6b/go.mod h1:+gauLs73omeJAPlsXcevLsJLKixV+sR/E7WSYTSx1fE=
|
||||
yunion.io/x/log v0.0.0-20190629062853-9f6483a7103d/go.mod h1:LC6f/4FozL0iaAbnFt2eDX9jlsyo3WiOUPm03d7+U4U=
|
||||
yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91 h1:inY5o3LDa/zgsIZuPN0HmpzKIsu/lLgsBmMttuDPGj4=
|
||||
|
||||
@@ -951,7 +951,22 @@ func (task *STask) ClearPendingUsage(index int) error {
|
||||
}
|
||||
|
||||
func (task *STask) GetParams() *jsonutils.JSONDict {
|
||||
return task.Params
|
||||
result := jsonutils.NewDict()
|
||||
if task.Params == nil {
|
||||
return result
|
||||
}
|
||||
copied := task.Params.DeepCopy()
|
||||
copyParams, ok := copied.(*jsonutils.JSONDict)
|
||||
if !ok || copyParams == nil {
|
||||
return result
|
||||
}
|
||||
paramsJsonMap, _ := copyParams.GetMap()
|
||||
for k, v := range paramsJsonMap {
|
||||
if !strings.HasPrefix(k, "__") {
|
||||
result.Set(k, v)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (task *STask) GetUserCred() mcclient.TokenCredential {
|
||||
|
||||
144
pkg/cloudcommon/db/taskman/tasks_test.go
Normal file
144
pkg/cloudcommon/db/taskman/tasks_test.go
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package taskman
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
)
|
||||
|
||||
func TestSTaskGetParams(t *testing.T) {
|
||||
newParams := func(pairs map[string]jsonutils.JSONObject) *jsonutils.JSONDict {
|
||||
params := jsonutils.NewDict()
|
||||
for k, v := range pairs {
|
||||
params.Set(k, v)
|
||||
}
|
||||
return params
|
||||
}
|
||||
|
||||
nested := jsonutils.NewDict()
|
||||
nested.Set("ip", jsonutils.NewString("10.0.0.1"))
|
||||
stages := jsonutils.NewArray(
|
||||
jsonutils.NewDict(),
|
||||
jsonutils.NewString("on_init"),
|
||||
)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
params *jsonutils.JSONDict
|
||||
want *jsonutils.JSONDict
|
||||
}{
|
||||
{
|
||||
name: "nil_params",
|
||||
params: nil,
|
||||
want: jsonutils.NewDict(),
|
||||
},
|
||||
{
|
||||
name: "empty_params",
|
||||
params: jsonutils.NewDict(),
|
||||
want: jsonutils.NewDict(),
|
||||
},
|
||||
{
|
||||
name: "keep_public_keys",
|
||||
params: newParams(map[string]jsonutils.JSONObject{
|
||||
"parent_task_id": jsonutils.NewString("task-1"),
|
||||
"auto_start": jsonutils.JSONTrue,
|
||||
}),
|
||||
want: newParams(map[string]jsonutils.JSONObject{
|
||||
"parent_task_id": jsonutils.NewString("task-1"),
|
||||
"auto_start": jsonutils.JSONTrue,
|
||||
}),
|
||||
},
|
||||
{
|
||||
name: "drop_internal_keys",
|
||||
params: newParams(map[string]jsonutils.JSONObject{
|
||||
"__stages": stages,
|
||||
"__pending_usage__": jsonutils.NewDict(),
|
||||
"__request_context": jsonutils.NewDict(),
|
||||
"__parent_task_notifyurl": jsonutils.NewString("http://notify"),
|
||||
}),
|
||||
want: jsonutils.NewDict(),
|
||||
},
|
||||
{
|
||||
name: "mixed_keys",
|
||||
params: newParams(map[string]jsonutils.JSONObject{
|
||||
"desc": nested,
|
||||
"__stages": stages,
|
||||
"_private": jsonutils.NewString("keep"),
|
||||
"__": jsonutils.NewString("drop"),
|
||||
"guest_id": jsonutils.NewString("g-1"),
|
||||
}),
|
||||
want: newParams(map[string]jsonutils.JSONObject{
|
||||
"desc": nested,
|
||||
"_private": jsonutils.NewString("keep"),
|
||||
"guest_id": jsonutils.NewString("g-1"),
|
||||
}),
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
c := c
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
task := &STask{}
|
||||
task.Params = c.params
|
||||
got := task.GetParams()
|
||||
if got == nil {
|
||||
t.Fatal("GetParams() returned nil, want empty dict")
|
||||
}
|
||||
if !got.Equals(c.want) {
|
||||
t.Fatalf("GetParams() = %s, want %s", got, c.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSTaskGetParamsDoesNotMutateOriginal(t *testing.T) {
|
||||
orig := jsonutils.NewDict()
|
||||
orig.Set("guest_id", jsonutils.NewString("g-1"))
|
||||
orig.Set("__stages", jsonutils.NewArray(jsonutils.NewString("on_init")))
|
||||
nested := jsonutils.NewDict()
|
||||
nested.Set("ip", jsonutils.NewString("10.0.0.1"))
|
||||
orig.Set("desc", nested)
|
||||
|
||||
task := &STask{STaskBase: STaskBase{Params: orig}}
|
||||
got := task.GetParams()
|
||||
got.Set("guest_id", jsonutils.NewString("g-2"))
|
||||
got.Set("extra", jsonutils.JSONTrue)
|
||||
desc, err := got.Get("desc")
|
||||
if err != nil {
|
||||
t.Fatalf("get desc: %v", err)
|
||||
}
|
||||
descDict, ok := desc.(*jsonutils.JSONDict)
|
||||
if !ok {
|
||||
t.Fatalf("desc type %T, want *jsonutils.JSONDict", desc)
|
||||
}
|
||||
descDict.Set("ip", jsonutils.NewString("10.0.0.2"))
|
||||
|
||||
if got.Contains("__stages") {
|
||||
t.Fatal("GetParams() leaked internal key __stages")
|
||||
}
|
||||
guestId, _ := orig.GetString("guest_id")
|
||||
if guestId != "g-1" {
|
||||
t.Fatalf("original guest_id = %s, want g-1", guestId)
|
||||
}
|
||||
if !orig.Contains("__stages") {
|
||||
t.Fatal("original __stages was removed")
|
||||
}
|
||||
origIp, _ := orig.GetString("desc", "ip")
|
||||
if origIp != "10.0.0.1" {
|
||||
t.Fatalf("original nested ip = %s, want 10.0.0.1", origIp)
|
||||
}
|
||||
}
|
||||
@@ -356,6 +356,7 @@ func (self *SBaremetalGuestDriver) RequestStartOnHost(ctx context.Context, guest
|
||||
if params.Length() > 0 {
|
||||
config.Add(params, "params")
|
||||
}
|
||||
log.Debugf("RequestStartOnHost config: %s", config.String())
|
||||
headers := task.GetTaskRequestHeader()
|
||||
url := fmt.Sprintf("/baremetals/%s/servers/%s/start", host.Id, guest.Id)
|
||||
_, err := host.BaremetalSyncRequest(ctx, "POST", url, headers, config)
|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -2672,7 +2672,7 @@ yunion.io/x/cloudmux/pkg/multicloud/zstack/provider
|
||||
yunion.io/x/executor/apis
|
||||
yunion.io/x/executor/client
|
||||
yunion.io/x/executor/server
|
||||
# yunion.io/x/jsonutils v1.0.1-0.20260715075349-615cfb44ff7c
|
||||
# yunion.io/x/jsonutils v1.0.1-0.20260916031541-8e0c8de6eb2e
|
||||
## explicit; go 1.18
|
||||
yunion.io/x/jsonutils
|
||||
# yunion.io/x/log v1.0.1-0.20240305175729-7cf2d6cd5a91
|
||||
|
||||
16
vendor/yunion.io/x/jsonutils/access.go
generated
vendored
16
vendor/yunion.io/x/jsonutils/access.go
generated
vendored
@@ -20,10 +20,18 @@ import (
|
||||
"time"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/pkg/sortedmap"
|
||||
"yunion.io/x/pkg/util/timeutils"
|
||||
)
|
||||
|
||||
func normalizeJSONObject(obj JSONObject) JSONObject {
|
||||
if gotypes.IsNil(obj) {
|
||||
return JSONNull
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
type JSONPair struct {
|
||||
key string
|
||||
val JSONObject
|
||||
@@ -40,7 +48,7 @@ func NewDict(objs ...JSONPair) *JSONDict {
|
||||
func NewArray(objs ...JSONObject) *JSONArray {
|
||||
arr := JSONArray{data: make([]JSONObject, 0, len(objs))}
|
||||
for _, o := range objs {
|
||||
arr.data = append(arr.data, o)
|
||||
arr.data = append(arr.data, normalizeJSONObject(o))
|
||||
}
|
||||
return &arr
|
||||
}
|
||||
@@ -74,7 +82,7 @@ func NewBool(val bool) *JSONBool {
|
||||
}
|
||||
|
||||
func (this *JSONDict) Set(key string, value JSONObject) {
|
||||
this.data = sortedmap.Add(this.data, key, value)
|
||||
this.data = sortedmap.Add(this.data, key, normalizeJSONObject(value))
|
||||
}
|
||||
|
||||
func (this *JSONDict) Remove(key string) bool {
|
||||
@@ -130,12 +138,12 @@ func (this *JSONDict) Add(o JSONObject, keys ...string) error {
|
||||
}
|
||||
|
||||
func (this *JSONArray) SetAt(idx int, obj JSONObject) {
|
||||
this.data[idx] = obj
|
||||
this.data[idx] = normalizeJSONObject(obj)
|
||||
}
|
||||
|
||||
func (this *JSONArray) Add(objs ...JSONObject) {
|
||||
for _, o := range objs {
|
||||
this.data = append(this.data, o)
|
||||
this.data = append(this.data, normalizeJSONObject(o))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
3
vendor/yunion.io/x/jsonutils/consts.go
generated
vendored
3
vendor/yunion.io/x/jsonutils/consts.go
generated
vendored
@@ -20,4 +20,7 @@ import (
|
||||
|
||||
const (
|
||||
TAG_DEPRECATED_BY = reflectutils.TAG_DEPRECATED_BY
|
||||
|
||||
// maxParseDepth is the maximum nesting level accepted by the parser
|
||||
maxParseDepth = 10000
|
||||
)
|
||||
|
||||
10
vendor/yunion.io/x/jsonutils/equals.go
generated
vendored
10
vendor/yunion.io/x/jsonutils/equals.go
generated
vendored
@@ -15,6 +15,7 @@
|
||||
package jsonutils
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/pkg/sortedmap"
|
||||
)
|
||||
|
||||
@@ -51,7 +52,14 @@ func (arr *JSONArray) Equals(json JSONObject) bool {
|
||||
return false
|
||||
}
|
||||
for i, v := range arr.data {
|
||||
if !v.Equals(arr2.data[i]) {
|
||||
oth := arr2.data[i]
|
||||
if gotypes.IsNil(v) || gotypes.IsNil(oth) {
|
||||
if gotypes.IsNil(v) != gotypes.IsNil(oth) {
|
||||
return false
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !v.Equals(oth) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
4
vendor/yunion.io/x/jsonutils/errors.go
generated
vendored
4
vendor/yunion.io/x/jsonutils/errors.go
generated
vendored
@@ -26,6 +26,10 @@ const (
|
||||
ErrInvalidHex = errors.Error("invalid hex")
|
||||
ErrInvalidRune = errors.Error("invalid 4 byte rune")
|
||||
|
||||
ErrInvalidNodeId = errors.Error("invalid node id")
|
||||
ErrDuplicateNodeId = errors.Error("duplicate node id")
|
||||
ErrNestedTooDeep = errors.Error("json nested too deep")
|
||||
|
||||
ErrTypeMismatch = errors.Error("unmarshal type mismatch")
|
||||
ErrArrayLengthMismatch = errors.Error("unmarshal array length mismatch")
|
||||
ErrInterfaceUnsupported = errors.Error("do not known how to deserialize json into this interface type")
|
||||
|
||||
12
vendor/yunion.io/x/jsonutils/interface.go
generated
vendored
12
vendor/yunion.io/x/jsonutils/interface.go
generated
vendored
@@ -15,6 +15,7 @@
|
||||
package jsonutils
|
||||
|
||||
import (
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/pkg/sortedmap"
|
||||
)
|
||||
|
||||
@@ -41,6 +42,10 @@ func (self *JSONString) Interface() interface{} {
|
||||
func (self *JSONArray) Interface() interface{} {
|
||||
ret := make([]interface{}, len(self.data))
|
||||
for i := 0; i < len(self.data); i += 1 {
|
||||
if gotypes.IsNil(self.data[i]) {
|
||||
ret[i] = nil
|
||||
continue
|
||||
}
|
||||
ret[i] = self.data[i].Interface()
|
||||
}
|
||||
return ret
|
||||
@@ -51,7 +56,12 @@ func (self *JSONDict) Interface() interface{} {
|
||||
|
||||
for iter := sortedmap.NewIterator(self.data); iter.HasMore(); iter.Next() {
|
||||
k, v := iter.Get()
|
||||
mapping[k] = v.(JSONObject).Interface()
|
||||
jo, _ := v.(JSONObject)
|
||||
if gotypes.IsNil(jo) {
|
||||
mapping[k] = nil
|
||||
continue
|
||||
}
|
||||
mapping[k] = jo.Interface()
|
||||
}
|
||||
|
||||
return mapping
|
||||
|
||||
49
vendor/yunion.io/x/jsonutils/jsonutils.go
generated
vendored
49
vendor/yunion.io/x/jsonutils/jsonutils.go
generated
vendored
@@ -259,7 +259,7 @@ func (s *sJsonParseSession) parseJSONValue(str []byte, offset int) (JSONObject,
|
||||
return nil, i, errors.Wrap(e, "parseString")
|
||||
} else if quote {
|
||||
return &JSONString{data: val}, i, nil
|
||||
} else if val[0] == '<' && val[len(val)-1] == '>' {
|
||||
} else if len(val) > 1 && val[0] == '<' && val[len(val)-1] == '>' {
|
||||
// Pointer <nnnn>
|
||||
val = val[1 : len(val)-1]
|
||||
ival, err := strconv.ParseInt(val, 10, 64)
|
||||
@@ -476,7 +476,11 @@ func (s *sJsonParseSession) parseDict(str []byte, offset int) (sortedmap.SSorted
|
||||
}
|
||||
if key == jsonPointerKey {
|
||||
// node id
|
||||
nodeId = int(val.(*JSONInt).data)
|
||||
jval, ok := val.(*JSONInt)
|
||||
if !ok {
|
||||
return smap, i, nodeId, errors.Wrap(ErrInvalidNodeId, jsonPointerKey)
|
||||
}
|
||||
nodeId = int(jval.data)
|
||||
} else {
|
||||
smap = sortedmap.Add(smap, key, val)
|
||||
}
|
||||
@@ -552,12 +556,20 @@ func (s *sJsonParseSession) parseArray(str []byte, offset int) ([]JSONObject, in
|
||||
}
|
||||
|
||||
func (this *JSONDict) parse(s *sJsonParseSession, str []byte, offset int) (int, error) {
|
||||
e := s.enter()
|
||||
if e != nil {
|
||||
return offset, errors.Wrap(e, "enter")
|
||||
}
|
||||
defer s.leave()
|
||||
smap, i, nodeId, e := s.parseDict(str, offset)
|
||||
if e == nil {
|
||||
this.nodeId = nodeId
|
||||
this.data = smap
|
||||
if this.nodeId > 0 {
|
||||
s.saveNode(nodeId, this)
|
||||
e = s.saveNode(nodeId, this)
|
||||
if e != nil {
|
||||
return i, errors.Wrap(e, "saveNode")
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
@@ -594,14 +606,19 @@ func (this *JSONDict) prettyString(level int) string {
|
||||
buffer.WriteByte('"')
|
||||
buffer.WriteString(k)
|
||||
buffer.WriteString("\":")
|
||||
_, okdict := v.(*JSONDict)
|
||||
_, okarray := v.(*JSONArray)
|
||||
if okdict || okarray {
|
||||
buffer.WriteByte('\n')
|
||||
buffer.WriteString(v.prettyString(level + 2))
|
||||
} else {
|
||||
if gotypes.IsNil(v) {
|
||||
buffer.WriteByte(' ')
|
||||
buffer.WriteString(v.String())
|
||||
buffer.WriteString("null")
|
||||
} else {
|
||||
_, okdict := v.(*JSONDict)
|
||||
_, okarray := v.(*JSONArray)
|
||||
if okdict || okarray {
|
||||
buffer.WriteByte('\n')
|
||||
buffer.WriteString(v.prettyString(level + 2))
|
||||
} else {
|
||||
buffer.WriteByte(' ')
|
||||
buffer.WriteString(v.String())
|
||||
}
|
||||
}
|
||||
idx++
|
||||
}
|
||||
@@ -614,6 +631,11 @@ func (this *JSONDict) prettyString(level int) string {
|
||||
}
|
||||
|
||||
func (this *JSONArray) parse(s *sJsonParseSession, str []byte, offset int) (int, error) {
|
||||
e := s.enter()
|
||||
if e != nil {
|
||||
return offset, errors.Wrap(e, "enter")
|
||||
}
|
||||
defer s.leave()
|
||||
val, i, e := s.parseArray(str, offset)
|
||||
if e == nil {
|
||||
this.data = val
|
||||
@@ -639,7 +661,12 @@ func (this *JSONArray) prettyString(level int) string {
|
||||
buffer.WriteString(",")
|
||||
}
|
||||
buffer.WriteByte('\n')
|
||||
buffer.WriteString(v.prettyString(level + 1))
|
||||
if gotypes.IsNil(v) {
|
||||
buffer.WriteString(tab)
|
||||
buffer.WriteString(" null")
|
||||
} else {
|
||||
buffer.WriteString(v.prettyString(level + 1))
|
||||
}
|
||||
}
|
||||
if len(this.data) > 0 {
|
||||
buffer.WriteByte('\n')
|
||||
|
||||
6
vendor/yunion.io/x/jsonutils/marshal.go
generated
vendored
6
vendor/yunion.io/x/jsonutils/marshal.go
generated
vendored
@@ -48,7 +48,7 @@ func (s *sJsonMarshalSession) marshalSlice(val reflect.Value, info *reflectutils
|
||||
objs := make([]JSONObject, 0)
|
||||
for i := 0; i < val.Len(); i += 1 {
|
||||
val := s.marshalValue(val.Index(i), nil, omitEmpty)
|
||||
if val != nil {
|
||||
if !gotypes.IsNil(val) {
|
||||
objs = append(objs, val)
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (s *sJsonMarshalSession) marshalMap(val reflect.Value, info *reflectutils.S
|
||||
for i := 0; i < len(keys); i += 1 {
|
||||
key := keys[i]
|
||||
val := s.marshalValue(val.MapIndex(key), nil, omitEmpty)
|
||||
if val != nil {
|
||||
if !gotypes.IsNil(val) {
|
||||
objPairs = append(objPairs, JSONPair{key: fmt.Sprintf("%s", key), val: val})
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,7 @@ func (s *sJsonMarshalSession) struct2JSONPairs(val reflect.Value, omitEmpty bool
|
||||
continue
|
||||
}
|
||||
val := s.marshalValue(fields[i].Value, jsonInfo, omitEmpty)
|
||||
if val != nil {
|
||||
if !gotypes.IsNil(val) {
|
||||
objPair := JSONPair{key: key, val: val}
|
||||
objPairs = append(objPairs, objPair)
|
||||
}
|
||||
|
||||
24
vendor/yunion.io/x/jsonutils/parse_session.go
generated
vendored
24
vendor/yunion.io/x/jsonutils/parse_session.go
generated
vendored
@@ -15,7 +15,7 @@
|
||||
package jsonutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"yunion.io/x/pkg/errors"
|
||||
)
|
||||
|
||||
type sNodeReferer struct {
|
||||
@@ -25,6 +25,9 @@ type sNodeReferer struct {
|
||||
|
||||
type sJsonParseSession struct {
|
||||
objectMap map[int]*sNodeReferer
|
||||
|
||||
// depth is the current nesting level of the object/array being parsed
|
||||
depth int
|
||||
}
|
||||
|
||||
func newJsonParseSession() *sJsonParseSession {
|
||||
@@ -33,6 +36,20 @@ func newJsonParseSession() *sJsonParseSession {
|
||||
}
|
||||
}
|
||||
|
||||
// enter records entering one more nesting level, it fails if the nesting
|
||||
// level exceeds maxParseDepth
|
||||
func (s *sJsonParseSession) enter() error {
|
||||
if s.depth >= maxParseDepth {
|
||||
return ErrNestedTooDeep
|
||||
}
|
||||
s.depth++
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sJsonParseSession) leave() {
|
||||
s.depth--
|
||||
}
|
||||
|
||||
func (s *sJsonParseSession) saveReferer(nodeId int, ptr *sJSONPointer) {
|
||||
if nr, ok := s.objectMap[nodeId]; ok {
|
||||
nr.pointers = append(nr.pointers, ptr)
|
||||
@@ -43,10 +60,10 @@ func (s *sJsonParseSession) saveReferer(nodeId int, ptr *sJSONPointer) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *sJsonParseSession) saveNode(nodeId int, node JSONObject) {
|
||||
func (s *sJsonParseSession) saveNode(nodeId int, node JSONObject) error {
|
||||
if nr, ok := s.objectMap[nodeId]; ok {
|
||||
if nr.node != nil {
|
||||
panic(fmt.Sprintf("nodeId %d alreayd exists: %s != %s", nodeId, nr.node, node))
|
||||
return errors.Wrapf(ErrDuplicateNodeId, "node id %d", nodeId)
|
||||
} else {
|
||||
nr.node = node
|
||||
}
|
||||
@@ -56,4 +73,5 @@ func (s *sJsonParseSession) saveNode(nodeId int, node JSONObject) {
|
||||
pointers: nil,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
21
vendor/yunion.io/x/jsonutils/write.go
generated
vendored
21
vendor/yunion.io/x/jsonutils/write.go
generated
vendored
@@ -18,9 +18,18 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"yunion.io/x/pkg/gotypes"
|
||||
"yunion.io/x/pkg/sortedmap"
|
||||
)
|
||||
|
||||
func writeJSONObject(sb *strings.Builder, v JSONObject) {
|
||||
if gotypes.IsNil(v) {
|
||||
sb.WriteString("null")
|
||||
return
|
||||
}
|
||||
v.buildString(sb)
|
||||
}
|
||||
|
||||
type writeSource interface {
|
||||
buildString(sb *strings.Builder)
|
||||
}
|
||||
@@ -46,6 +55,10 @@ func (this *JSONBool) buildString(sb *strings.Builder) {
|
||||
}
|
||||
|
||||
func (this *JSONDict) buildString(sb *strings.Builder) {
|
||||
if this == nil {
|
||||
sb.WriteString("null")
|
||||
return
|
||||
}
|
||||
sb.WriteByte('{')
|
||||
var idx = 0
|
||||
if this.nodeId > 0 {
|
||||
@@ -63,19 +76,23 @@ func (this *JSONDict) buildString(sb *strings.Builder) {
|
||||
sb.WriteString(quoteString(k))
|
||||
sb.WriteByte(':')
|
||||
|
||||
v.buildString(sb)
|
||||
writeJSONObject(sb, v)
|
||||
idx++
|
||||
}
|
||||
sb.WriteByte('}')
|
||||
}
|
||||
|
||||
func (this *JSONArray) buildString(sb *strings.Builder) {
|
||||
if this == nil {
|
||||
sb.WriteString("null")
|
||||
return
|
||||
}
|
||||
sb.WriteByte('[')
|
||||
for idx, v := range this.data {
|
||||
if idx > 0 {
|
||||
sb.WriteByte(',')
|
||||
}
|
||||
v.buildString(sb)
|
||||
writeJSONObject(sb, v)
|
||||
}
|
||||
sb.WriteByte(']')
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user