mxj.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // mxj - A collection of map[string]interface{} and associated XML and JSON utilities.
  2. // Copyright 2012-2014 Charles Banning. All rights reserved.
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file
  5. package mxj
  6. import (
  7. "fmt"
  8. "sort"
  9. )
  10. const (
  11. Cast = true // for clarity - e.g., mxj.NewMapXml(doc, mxj.Cast)
  12. SafeEncoding = true // ditto - e.g., mv.Json(mxj.SafeEncoding)
  13. )
  14. type Map map[string]interface{}
  15. // Allocate a Map.
  16. func New() Map {
  17. m := make(map[string]interface{}, 0)
  18. return m
  19. }
  20. // Cast a Map to map[string]interface{}
  21. func (mv Map) Old() map[string]interface{} {
  22. return mv
  23. }
  24. // Return a copy of mv as a newly allocated Map. If the Map only contains string,
  25. // numeric, map[string]interface{}, and []interface{} values, then it can be thought
  26. // of as a "deep copy." Copying a structure (or structure reference) value is subject
  27. // to the noted restrictions.
  28. // NOTE: If 'mv' includes structure values with, possibly, JSON encoding tags
  29. // then only public fields of the structure are in the new Map - and with
  30. // keys that conform to any encoding tag instructions. The structure itself will
  31. // be represented as a map[string]interface{} value.
  32. func (mv Map) Copy() (Map, error) {
  33. // this is the poor-man's deep copy
  34. // not efficient, but it works
  35. j, jerr := mv.Json()
  36. // must handle, we don't know how mv got built
  37. if jerr != nil {
  38. return nil, jerr
  39. }
  40. return NewMapJson(j)
  41. }
  42. // --------------- StringIndent ... from x2j.WriteMap -------------
  43. // Pretty print a Map.
  44. func (mv Map) StringIndent(offset ...int) string {
  45. return writeMap(map[string]interface{}(mv), true, true, offset...)
  46. }
  47. // Pretty print a Map without the value type information - just key:value entries.
  48. func (mv Map) StringIndentNoTypeInfo(offset ...int) string {
  49. return writeMap(map[string]interface{}(mv), false, true, offset...)
  50. }
  51. // writeMap - dumps the map[string]interface{} for examination.
  52. // 'typeInfo' causes value type to be printed.
  53. // 'offset' is initial indentation count; typically: Write(m).
  54. func writeMap(m interface{}, typeInfo, root bool, offset ...int) string {
  55. var indent int
  56. if len(offset) == 1 {
  57. indent = offset[0]
  58. }
  59. var s string
  60. switch m.(type) {
  61. case []interface{}:
  62. if typeInfo {
  63. s += "[[]interface{}]"
  64. }
  65. for _, v := range m.([]interface{}) {
  66. s += "\n"
  67. for i := 0; i < indent; i++ {
  68. s += " "
  69. }
  70. s += writeMap(v, typeInfo, false, indent+1)
  71. }
  72. case map[string]interface{}:
  73. list := make([][2]string, len(m.(map[string]interface{})))
  74. var n int
  75. for k, v := range m.(map[string]interface{}) {
  76. list[n][0] = k
  77. list[n][1] = writeMap(v, typeInfo, false, indent+1)
  78. n++
  79. }
  80. sort.Sort(mapList(list))
  81. for _, v := range list {
  82. if root {
  83. root = false
  84. } else {
  85. s += "\n"
  86. }
  87. for i := 0; i < indent; i++ {
  88. s += " "
  89. }
  90. s += v[0] + " : " + v[1]
  91. }
  92. default:
  93. if typeInfo {
  94. s += fmt.Sprintf("[%T] %+v", m, m)
  95. } else {
  96. s += fmt.Sprintf("%+v", m)
  97. }
  98. }
  99. return s
  100. }
  101. // ======================== utility ===============
  102. type mapList [][2]string
  103. func (ml mapList) Len() int {
  104. return len(ml)
  105. }
  106. func (ml mapList) Swap(i, j int) {
  107. ml[i], ml[j] = ml[j], ml[i]
  108. }
  109. func (ml mapList) Less(i, j int) bool {
  110. return ml[i][0] <= ml[j][0]
  111. }