Search code examples
gotoml

Parsing a key value pair within a table for TOML file and golang


I have the following structure for a TOML file:

[database]
host = "localhost"
port = 8086
https = true
username = "root"
password = "root"
db = "test"

[cloud]
deviceType = "2be386e9bbae"
deviceId = "119a705fa3b1"
password = "test"
token = "dqpx5vNLLTR34"
endpoint = "mqtts://mqtt1.endpoint.com"

[gps]
#measurement = "gps"
  [gps.msgpack]
  topic = "/evt/gps/msgpack"

  [gps.json]
  topic = "/evt/gps/json"

[imu]
#measurement = "imu"
  [imu.1]
    tag = "NODE1"
    topic = "/evt/imu1/msgpack"
  [imu.2]
    tag = "NODE2"
    topic = "/evt/imu2/msgpack"

I want to set measurement key in gps table and imutable only once and not redundantly within msgpack and json and for 1 and 2

With the commented out keys The following code works

Code

package main

import (
  "fmt"
  "github.com/BurntSushi/toml"
)

type imu struct {
  Topic string
  Measurement string
  Tag string
}

type gps struct {
  // Measurement string
  Measurement string
  ETopic string `toml:"topic"`
}

type database struct {
  Host  string
  Port  int
  Https bool
  Username  string
  Password  string
  Dbname  string
}

type cloud struct {
  Devicetype  string
  DeviceId  string
  Password  string
  Token   string
  Endpoint  string
}

type tomlConfig struct {
  DB database `toml:"database"`
  Cloud cloud `toml:"cloud"`
  Gps map[string]gps `toml:"gps"`
  Imu map[string]imu  `toml:"imu"`
}


func main()  {

  var config tomlConfig

  if _, err := toml.DecodeFile("cloud.toml", &config); err != nil {
    fmt.Println(err)
    return
  }
  // fmt.Printf("%#v\n", config)
  for sensorName, sensor := range config.Imu {
    fmt.Printf("Topic: %s %s %s %s\n", sensorName, sensor.Topic, sensor.Tag, sensor.Measurement)
  }

  for types, gps := range config.Gps {
    fmt.Printf("%s\n", types)
    fmt.Printf("%s\n", gps.ETopic)
  }
}

However on uncommenting out the key value pair I get the following:

 toml: type mismatch for main.gps: expected table but found string

(It should still be a valid TOML, as I translated it to JSON and checked the structure)

I understand that I have not mentioned within the struct that I need to add a string for it. However I am getting confused as to how the struct should now look like.


Solution

  • You say:

    I want to set measurement key in gps table and imutable only once and not redundantly within msgpack and json and for 1 and 2

    You don't make this because creator of TOML format said:

    Because we need a decent human-readable format that unambiguously maps to a hash table and the YAML spec is like 80 pages long and gives me rage. No, JSON doesn't count. You know why.

    If you need to have the same value to one key, for you example, measurement, you must specify it in every subtable what you want

    Your correct TOML file:

    [database]
    host = "localhost"
    port = 8086
    https = true
    username = "root"
    password = "root"
    db = "test"
    
    [cloud]
    deviceType = "2be386e9bbae"
    deviceId = "119a705fa3b1"
    password = "test"
    token = "dqpx5vNLLTR34"
    endpoint = "mqtts://mqtt1.endpoint.com"
    
    [gps]
    [gps.msgpack]
    topic = "/evt/gps/msgpack"
    measurement = "gps"
    
    [gps.json]
    topic = "/evt/gps/json"
    measurement = "gps"
    
    [imu]
    [imu.1]
    measurement = "imu"
    tag = "NODE1"
    topic = "/evt/imu1/msgpack"
    [imu.2]
    measurement = "imu"
    tag = "NODE2"
    topic = "/evt/imu2/msgpack"