gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/main.go (about) 1 // Command toml-test-encoder satisfies the toml-test interface for testing 2 // TOML encoders. Namely, it accepts JSON on stdin and outputs TOML on stdout. 3 package main 4 5 import ( 6 "encoding/json" 7 "flag" 8 "log" 9 "os" 10 "path" 11 "strconv" 12 "time" 13 14 "github.com/BurntSushi/toml" 15 ) 16 17 func init() { 18 log.SetFlags(0) 19 20 flag.Usage = usage 21 flag.Parse() 22 } 23 24 func usage() { 25 log.Printf("Usage: %s < json-file\n", path.Base(os.Args[0])) 26 flag.PrintDefaults() 27 28 os.Exit(1) 29 } 30 31 func main() { 32 if flag.NArg() != 0 { 33 flag.Usage() 34 } 35 36 var tmp interface{} 37 if err := json.NewDecoder(os.Stdin).Decode(&tmp); err != nil { 38 log.Fatalf("Error decoding JSON: %s", err) 39 } 40 41 tomlData := translate(tmp) 42 if err := toml.NewEncoder(os.Stdout).Encode(tomlData); err != nil { 43 log.Fatalf("Error encoding TOML: %s", err) 44 } 45 } 46 47 func translate(typedJson interface{}) interface{} { 48 switch v := typedJson.(type) { 49 case map[string]interface{}: 50 if len(v) == 2 && in("type", v) && in("value", v) { 51 return untag(v) 52 } 53 m := make(map[string]interface{}, len(v)) 54 for k, v2 := range v { 55 m[k] = translate(v2) 56 } 57 return m 58 case []interface{}: 59 tabArray := make([]map[string]interface{}, len(v)) 60 for i := range v { 61 if m, ok := translate(v[i]).(map[string]interface{}); ok { 62 tabArray[i] = m 63 } else { 64 log.Fatalf("JSON arrays may only contain objects. This " + 65 "corresponds to only tables being allowed in " + 66 "TOML table arrays.") 67 } 68 } 69 return tabArray 70 } 71 log.Fatalf("Unrecognized JSON format '%T'.", typedJson) 72 panic("unreachable") 73 } 74 75 func untag(typed map[string]interface{}) interface{} { 76 t := typed["type"].(string) 77 v := typed["value"] 78 switch t { 79 case "string": 80 return v.(string) 81 case "integer": 82 v := v.(string) 83 n, err := strconv.Atoi(v) 84 if err != nil { 85 log.Fatalf("Could not parse '%s' as integer: %s", v, err) 86 } 87 return n 88 case "float": 89 v := v.(string) 90 f, err := strconv.ParseFloat(v, 64) 91 if err != nil { 92 log.Fatalf("Could not parse '%s' as float64: %s", v, err) 93 } 94 return f 95 case "datetime": 96 v := v.(string) 97 t, err := time.Parse("2006-01-02T15:04:05Z", v) 98 if err != nil { 99 log.Fatalf("Could not parse '%s' as a datetime: %s", v, err) 100 } 101 return t 102 case "bool": 103 v := v.(string) 104 switch v { 105 case "true": 106 return true 107 case "false": 108 return false 109 } 110 log.Fatalf("Could not parse '%s' as a boolean.", v) 111 case "array": 112 v := v.([]interface{}) 113 array := make([]interface{}, len(v)) 114 for i := range v { 115 if m, ok := v[i].(map[string]interface{}); ok { 116 array[i] = untag(m) 117 } else { 118 log.Fatalf("Arrays may only contain other arrays or "+ 119 "primitive values, but found a '%T'.", m) 120 } 121 } 122 return array 123 } 124 log.Fatalf("Unrecognized tag type '%s'.", t) 125 panic("unreachable") 126 } 127 128 func in(key string, m map[string]interface{}) bool { 129 _, ok := m[key] 130 return ok 131 }