marshal.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package jsonutils
  15. /**
  16. jsonutils.Marshal
  17. Convert any object to JSONObject
  18. */
  19. import (
  20. "fmt"
  21. "reflect"
  22. "sort"
  23. "time"
  24. "yunion.io/x/log"
  25. "yunion.io/x/pkg/gotypes"
  26. "yunion.io/x/pkg/tristate"
  27. "yunion.io/x/pkg/util/reflectutils"
  28. "yunion.io/x/pkg/util/timeutils"
  29. )
  30. func (s *sJsonMarshalSession) marshalSlice(val reflect.Value, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  31. if val.Kind() == reflect.Slice && val.IsNil() {
  32. if !omitEmpty {
  33. return JSONNull
  34. } else {
  35. return nil
  36. }
  37. }
  38. if val.Len() == 0 && info != nil && info.OmitEmpty && omitEmpty {
  39. return nil
  40. }
  41. objs := make([]JSONObject, 0)
  42. for i := 0; i < val.Len(); i += 1 {
  43. val := s.marshalValue(val.Index(i), nil, omitEmpty)
  44. if val != nil {
  45. objs = append(objs, val)
  46. }
  47. }
  48. arr := NewArray(objs...)
  49. if info != nil && info.ForceString {
  50. return NewString(arr.String())
  51. } else {
  52. return arr
  53. }
  54. }
  55. type tMapKeys []reflect.Value
  56. func (a tMapKeys) Len() int { return len(a) }
  57. func (a tMapKeys) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
  58. func (a tMapKeys) Less(i, j int) bool { return a[i].String() < a[j].String() }
  59. func (s *sJsonMarshalSession) marshalMap(val reflect.Value, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  60. if val.IsNil() {
  61. if !omitEmpty {
  62. return JSONNull
  63. } else {
  64. return nil
  65. }
  66. }
  67. keys := val.MapKeys()
  68. if len(keys) == 0 && info != nil && info.OmitEmpty && omitEmpty {
  69. return nil
  70. }
  71. // sort keys
  72. sort.Sort(tMapKeys(keys))
  73. objPairs := make([]JSONPair, 0)
  74. for i := 0; i < len(keys); i += 1 {
  75. key := keys[i]
  76. val := s.marshalValue(val.MapIndex(key), nil, omitEmpty)
  77. if val != nil {
  78. objPairs = append(objPairs, JSONPair{key: fmt.Sprintf("%s", key), val: val})
  79. }
  80. }
  81. dict := NewDict(objPairs...)
  82. if info != nil && info.ForceString {
  83. return NewString(dict.String())
  84. } else {
  85. return dict
  86. }
  87. }
  88. func (s *sJsonMarshalSession) marshalStruct(val reflect.Value, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  89. objPairs := s.struct2JSONPairs(val, omitEmpty)
  90. if len(objPairs) == 0 && info != nil && info.OmitEmpty && omitEmpty {
  91. return nil
  92. }
  93. dict := NewDict(objPairs...)
  94. if info != nil && info.ForceString {
  95. return NewString(dict.String())
  96. } else {
  97. return dict
  98. }
  99. }
  100. func findValueByKey(pairs []JSONPair, key string) JSONObject {
  101. for i := range pairs {
  102. if pairs[i].key == key {
  103. return pairs[i].val
  104. }
  105. }
  106. return nil
  107. }
  108. func (s *sJsonMarshalSession) struct2JSONPairs(val reflect.Value, omitEmpty bool) []JSONPair {
  109. fields := reflectutils.FetchStructFieldValueSet(val)
  110. objPairs := make([]JSONPair, 0, len(fields))
  111. depFields := make(map[string]string)
  112. for i := 0; i < len(fields); i += 1 {
  113. jsonInfo := fields[i].Info
  114. if jsonInfo.Ignore {
  115. continue
  116. }
  117. key := jsonInfo.MarshalName()
  118. if deprecatedBy, ok := fields[i].Info.Tags[TAG_DEPRECATED_BY]; ok {
  119. depFields[key] = deprecatedBy
  120. continue
  121. }
  122. val := s.marshalValue(fields[i].Value, jsonInfo, omitEmpty)
  123. if val != nil {
  124. objPair := JSONPair{key: key, val: val}
  125. objPairs = append(objPairs, objPair)
  126. }
  127. }
  128. depPairs := make([]JSONPair, 0, len(depFields))
  129. for depKey, key := range depFields {
  130. findLoop := false
  131. for {
  132. if okey, ok := depFields[key]; ok {
  133. if okey == depKey {
  134. // loop detected
  135. findLoop = true
  136. break
  137. }
  138. key = okey
  139. } else {
  140. break
  141. }
  142. }
  143. if findLoop {
  144. continue
  145. }
  146. val := findValueByKey(objPairs, key)
  147. if val != nil {
  148. objPair := JSONPair{key: depKey, val: val}
  149. depPairs = append(depPairs, objPair)
  150. }
  151. }
  152. objPairs = append(objPairs, depPairs...)
  153. return objPairs
  154. }
  155. func marshalInt64(val int64, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  156. if val == 0 && info != nil && info.OmitZero && omitEmpty {
  157. return nil
  158. } else if info != nil && info.ForceString {
  159. return NewString(fmt.Sprintf("%d", val))
  160. } else {
  161. return NewInt(val)
  162. }
  163. }
  164. func marshalFloat64(val float64, info *reflectutils.SStructFieldInfo, bit int, omitEmpty bool) JSONObject {
  165. if val == 0.0 && info != nil && info.OmitZero && omitEmpty {
  166. return nil
  167. } else if info != nil && info.ForceString {
  168. return NewString(fmt.Sprintf("%f", val))
  169. } else {
  170. return NewFloat64(val)
  171. }
  172. }
  173. func marshalFloat32(val float32, info *reflectutils.SStructFieldInfo, bit int, omitEmpty bool) JSONObject {
  174. if val == 0.0 && info != nil && info.OmitZero && omitEmpty {
  175. return nil
  176. } else if info != nil && info.ForceString {
  177. return NewString(fmt.Sprintf("%f", val))
  178. } else {
  179. return NewFloat32(val)
  180. }
  181. }
  182. func marshalBoolean(val bool, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  183. if !val && info != nil && info.OmitFalse && omitEmpty {
  184. return nil
  185. } else if info != nil && info.ForceString {
  186. return NewString(fmt.Sprintf("%v", val))
  187. } else {
  188. if val {
  189. return JSONTrue
  190. } else {
  191. return JSONFalse
  192. }
  193. }
  194. }
  195. func marshalTristate(val tristate.TriState, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  196. if val.IsTrue() {
  197. return JSONTrue
  198. } else if val.IsFalse() {
  199. return JSONFalse
  200. } else {
  201. if omitEmpty {
  202. return nil
  203. } else {
  204. return JSONNull
  205. }
  206. }
  207. }
  208. func marshalString(val string, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  209. if len(val) == 0 && info != nil && info.OmitEmpty && omitEmpty {
  210. return nil
  211. } else {
  212. return NewString(val)
  213. }
  214. }
  215. func marshalTime(val time.Time, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  216. if val.IsZero() {
  217. if info != nil && info.OmitEmpty && omitEmpty {
  218. return nil
  219. }
  220. return NewString("")
  221. } else {
  222. return NewString(timeutils.FullIsoTime(val))
  223. }
  224. }
  225. func Marshal(obj interface{}) JSONObject {
  226. if obj == nil {
  227. return JSONNull
  228. }
  229. val := reflect.ValueOf(obj)
  230. if kind := val.Kind(); val.IsZero() && kind == reflect.Ptr {
  231. return JSONNull
  232. }
  233. s := newJsonMarshalSession()
  234. mval := s.marshalValue(val, nil, true)
  235. s.setAllNodeId()
  236. if mval == nil {
  237. return JSONNull
  238. }
  239. return mval
  240. }
  241. func (s *sJsonMarshalSession) marshalValue(objValue reflect.Value, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  242. return tryStdMarshal(objValue, func(v reflect.Value) JSONObject {
  243. return s.marshalValueWithObjectMap(v, info, omitEmpty)
  244. })
  245. }
  246. func (s *sJsonMarshalSession) marshalValueWithObjectMap(objValue reflect.Value, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  247. var jsonPtr *sJSONPointer
  248. if objValue.Kind() == reflect.Ptr {
  249. inf := objValue.Interface()
  250. if !gotypes.IsNil(inf) {
  251. jsonPtrNode := s.objectTrace.find(inf)
  252. if jsonPtrNode != nil {
  253. // loop detected!
  254. return jsonPtrNode.pointer
  255. }
  256. jsonPtr = s.newJsonPointer(inf)
  257. }
  258. }
  259. jsonObj := s._marshalValue(objValue, info, omitEmpty)
  260. if jsonPtr != nil {
  261. s.setJsonObject(jsonPtr, jsonObj)
  262. }
  263. return jsonObj
  264. }
  265. func (s *sJsonMarshalSession) _marshalValue(objValue reflect.Value, info *reflectutils.SStructFieldInfo, omitEmpty bool) JSONObject {
  266. switch objValue.Type() {
  267. case JSONDictPtrType, JSONArrayPtrType, JSONBoolPtrType, JSONIntPtrType, JSONFloatPtrType, JSONStringPtrType, JSONObjectType:
  268. if objValue.IsNil() {
  269. if omitEmpty {
  270. return nil
  271. } else {
  272. return JSONNull
  273. }
  274. }
  275. return objValue.Interface().(JSONObject)
  276. case JSONDictType:
  277. json, ok := objValue.Interface().(JSONDict)
  278. if ok {
  279. if len(json.data) == 0 && info != nil && info.OmitEmpty && omitEmpty {
  280. return nil
  281. } else {
  282. return &json
  283. }
  284. } else {
  285. return nil
  286. }
  287. case JSONArrayType:
  288. json, ok := objValue.Interface().(JSONArray)
  289. if ok {
  290. if len(json.data) == 0 && info != nil && info.OmitEmpty && omitEmpty {
  291. return nil
  292. } else {
  293. return &json
  294. }
  295. } else {
  296. return nil
  297. }
  298. case JSONBoolType:
  299. json, ok := objValue.Interface().(JSONBool)
  300. if ok {
  301. if !json.data && info != nil && info.OmitEmpty && omitEmpty {
  302. return nil
  303. } else {
  304. return &json
  305. }
  306. } else {
  307. return nil
  308. }
  309. case JSONIntType:
  310. json, ok := objValue.Interface().(JSONInt)
  311. if ok {
  312. if json.data == 0 && info != nil && info.OmitEmpty && omitEmpty {
  313. return nil
  314. } else {
  315. return &json
  316. }
  317. } else {
  318. return nil
  319. }
  320. case JSONFloatType:
  321. json, ok := objValue.Interface().(JSONFloat)
  322. if ok {
  323. if json.data == 0.0 && info != nil && info.OmitEmpty && omitEmpty {
  324. return nil
  325. } else {
  326. return &json
  327. }
  328. } else {
  329. return nil
  330. }
  331. case JSONStringType:
  332. json, ok := objValue.Interface().(JSONString)
  333. if ok {
  334. if len(json.data) == 0 && info != nil && info.OmitEmpty && omitEmpty {
  335. return nil
  336. } else {
  337. return &json
  338. }
  339. } else {
  340. return nil
  341. }
  342. case tristate.TriStateType:
  343. tri, ok := objValue.Interface().(tristate.TriState)
  344. if ok {
  345. return marshalTristate(tri, info, omitEmpty)
  346. } else {
  347. return nil
  348. }
  349. }
  350. switch objValue.Kind() {
  351. case reflect.Slice, reflect.Array:
  352. return s.marshalSlice(objValue, info, omitEmpty)
  353. case reflect.Struct:
  354. if objValue.Type() == gotypes.TimeType {
  355. return marshalTime(objValue.Interface().(time.Time), info, omitEmpty)
  356. } else {
  357. return s.marshalStruct(objValue, info, omitEmpty)
  358. }
  359. case reflect.Map:
  360. return s.marshalMap(objValue, info, omitEmpty)
  361. case reflect.String:
  362. strValue := objValue.Convert(gotypes.StringType)
  363. return marshalString(strValue.Interface().(string), info, omitEmpty)
  364. case reflect.Bool:
  365. return marshalBoolean(objValue.Interface().(bool), info, omitEmpty)
  366. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  367. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  368. intValue := objValue.Convert(gotypes.Int64Type)
  369. return marshalInt64(intValue.Interface().(int64), info, omitEmpty)
  370. case reflect.Float32:
  371. floatVal := objValue.Convert(gotypes.Float32Type)
  372. return marshalFloat32(floatVal.Interface().(float32), info, 32, omitEmpty)
  373. case reflect.Float64:
  374. floatVal := objValue.Convert(gotypes.Float64Type)
  375. return marshalFloat64(floatVal.Interface().(float64), info, 64, omitEmpty)
  376. case reflect.Interface, reflect.Ptr:
  377. if objValue.IsNil() {
  378. if omitEmpty {
  379. return nil
  380. } else {
  381. return JSONNull
  382. }
  383. }
  384. return s.marshalValue(objValue.Elem(), info, omitEmpty)
  385. default:
  386. log.Errorf("unsupport object %s %s", objValue.Type(), objValue.Interface())
  387. return JSONNull
  388. }
  389. }
  390. func MarshalAll(obj interface{}) JSONObject {
  391. if obj == nil {
  392. return JSONNull
  393. }
  394. val := reflect.ValueOf(obj)
  395. if kind := val.Kind(); val.IsZero() && kind == reflect.Ptr {
  396. return JSONNull
  397. }
  398. s := newJsonMarshalSession()
  399. mval := s.marshalValue(val, nil, false)
  400. s.setAllNodeId()
  401. if mval == nil {
  402. return JSONNull
  403. }
  404. return mval
  405. }