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  }