| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- package main
- import (
- "encoding/json"
- "flag"
- "log"
- "os"
- "path"
- "strconv"
- "time"
- "github.com/coreos/etcd/third_party/github.com/BurntSushi/toml"
- )
- func init() {
- log.SetFlags(0)
- flag.Usage = usage
- flag.Parse()
- }
- func usage() {
- log.Printf("Usage: %s < json-file\n", path.Base(os.Args[0]))
- flag.PrintDefaults()
- os.Exit(1)
- }
- func main() {
- if flag.NArg() != 0 {
- flag.Usage()
- }
- var tmp interface{}
- if err := json.NewDecoder(os.Stdin).Decode(&tmp); err != nil {
- log.Fatalf("Error decoding JSON: %s", err)
- }
- tomlData := translate(tmp)
- if err := toml.NewEncoder(os.Stdout).Encode(tomlData); err != nil {
- log.Fatalf("Error encoding TOML: %s", err)
- }
- }
- func translate(typedJson interface{}) interface{} {
- switch v := typedJson.(type) {
- case map[string]interface{}:
- if len(v) == 2 && in("type", v) && in("value", v) {
- return untag(v)
- }
- m := make(map[string]interface{}, len(v))
- for k, v2 := range v {
- m[k] = translate(v2)
- }
- return m
- case []interface{}:
- tabArray := make([]map[string]interface{}, len(v))
- for i := range v {
- if m, ok := translate(v[i]).(map[string]interface{}); ok {
- tabArray[i] = m
- } else {
- log.Fatalf("JSON arrays may only contain objects. This " +
- "corresponds to only tables being allowed in " +
- "TOML table arrays.")
- }
- }
- return tabArray
- }
- log.Fatalf("Unrecognized JSON format '%T'.", typedJson)
- panic("unreachable")
- }
- func untag(typed map[string]interface{}) interface{} {
- t := typed["type"].(string)
- v := typed["value"]
- switch t {
- case "string":
- return v.(string)
- case "integer":
- v := v.(string)
- n, err := strconv.Atoi(v)
- if err != nil {
- log.Fatalf("Could not parse '%s' as integer: %s", v, err)
- }
- return n
- case "float":
- v := v.(string)
- f, err := strconv.ParseFloat(v, 64)
- if err != nil {
- log.Fatalf("Could not parse '%s' as float64: %s", v, err)
- }
- return f
- case "datetime":
- v := v.(string)
- t, err := time.Parse("2006-01-02T15:04:05Z", v)
- if err != nil {
- log.Fatalf("Could not parse '%s' as a datetime: %s", v, err)
- }
- return t
- case "bool":
- v := v.(string)
- switch v {
- case "true":
- return true
- case "false":
- return false
- }
- log.Fatalf("Could not parse '%s' as a boolean.", v)
- case "array":
- v := v.([]interface{})
- array := make([]interface{}, len(v))
- for i := range v {
- if m, ok := v[i].(map[string]interface{}); ok {
- array[i] = untag(m)
- } else {
- log.Fatalf("Arrays may only contain other arrays or "+
- "primitive values, but found a '%T'.", m)
- }
- }
- return array
- }
- log.Fatalf("Unrecognized tag type '%s'.", t)
- panic("unreachable")
- }
- func in(key string, m map[string]interface{}) bool {
- _, ok := m[key]
- return ok
- }
|