github.com/turingchain2020/turingchain@v1.1.21/cmd/jsfmt/main.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // package main js转换 -> 6 // 1. 格式化 7 // 2. 默认int 类型除以 8,保留4位小数 8 package main 9 10 import ( 11 "bufio" 12 "encoding/json" 13 "flag" 14 "fmt" 15 "math" 16 "os" 17 "strings" 18 ) 19 20 var d = flag.Int("d", 8, "数字小数点位数") 21 var n = flag.Int("n", 4, "保留有效小数点位数") 22 var js = flag.String("js", "", "输入js字符串") 23 var keylist = flag.String("k", "", "key list") 24 var keymap = make(map[string]bool) 25 26 func main() { 27 flag.Parse() 28 list := strings.Split(*keylist, ",") 29 for _, v := range list { 30 keymap[v] = true 31 } 32 if *js == "" { 33 reader := bufio.NewReader(os.Stdin) 34 *js, _ = reader.ReadString('\n') 35 } 36 var data interface{} 37 err := json.Unmarshal([]byte(*js), &data) 38 if err != nil { 39 panic(err) 40 } 41 s := parse("", data, *d, *n) 42 jsf, _ := json.Marshal(s) 43 fmt.Println(string(jsf)) 44 } 45 46 /* 47 bool, for JSON booleans 48 float64, for JSON numbers 49 string, for JSON strings 50 []interface{}, for JSON arrays 51 map[string]interface{}, for JSON objects 52 nil for JSON null 53 */ 54 func parse(key string, data interface{}, d, n int) interface{} { 55 if data == nil { 56 return data 57 } 58 switch data.(type) { 59 case bool: 60 return data 61 case string: 62 if !isValidNumber(data.(string)) { 63 return data 64 } 65 numstr := data.(string) 66 num := json.Number(numstr) 67 if strings.Contains(numstr, ".") { 68 dm, _ := num.Float64() 69 return format64(key, dm, d, n) 70 } 71 dm, _ := num.Int64() 72 return format64(key, float64(dm), d, n) 73 case float64: 74 num := data.(float64) 75 return format64(key, num, d, n) 76 case []interface{}: 77 datas := data.([]interface{}) 78 for i := range datas { 79 datas[i] = parse(key, datas[i], d, n) 80 } 81 case map[string]interface{}: 82 datas := data.(map[string]interface{}) 83 for i := range datas { 84 datas[i] = parse(i, datas[i], d, n) 85 } 86 } 87 return data 88 } 89 90 func format64(key string, num float64, d, n int) interface{} { 91 if len(keymap) > 0 && !keymap[key] { 92 return num 93 } 94 div := math.Pow(10, float64(n)) 95 if div == 0 { 96 return num 97 } 98 num = num / div 99 return fmt.Sprintf("%."+fmt.Sprint(n)+"f", num) 100 } 101 102 func isValidNumber(s string) bool { 103 if s == "" { 104 return false 105 } 106 // Optional - 107 if s[0] == '-' { 108 s = s[1:] 109 if s == "" { 110 return false 111 } 112 } 113 // Digits 114 switch { 115 default: 116 return false 117 118 case s[0] == '0': 119 s = s[1:] 120 121 case '1' <= s[0] && s[0] <= '9': 122 s = s[1:] 123 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { 124 s = s[1:] 125 } 126 } 127 // . followed by 1 or more digits. 128 if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' { 129 s = s[2:] 130 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { 131 s = s[1:] 132 } 133 } 134 // e or E followed by an optional - or + and 135 // 1 or more digits. 136 if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') { 137 s = s[1:] 138 if s[0] == '+' || s[0] == '-' { 139 s = s[1:] 140 if s == "" { 141 return false 142 } 143 } 144 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { 145 s = s[1:] 146 } 147 } 148 // Make sure we are at the end. 149 return s == "" 150 }