toml

V标准库包含了toml模块,toml模块是用纯V开发实现的,没有任何第三方依赖,目前完全兼容toml v1.0.0规范,使用toml模块可以很方便地使用toml作为配置文件。

解析toml

解析指定的toml文件:

pub fn parse_file(path string) !Doc

解析指定的toml文本:

pub fn parse_text(text string) !Doc

获取节点的值

解析完toml文件或文本后,返回一个Doc类型,可以调用Doc.value方法,获取节点的值,value返回Any类型,Any是一个联合类型,包含所有节点的类型种类。

并且value的参数key,可以通过点号表示toml的层级,这样就可以直接通过层级关系,获取所需节点的值。

pub fn (d Doc) value(key string) Any
pub type Any = Date	//日期类型
	| DateTime	//日期时间类型
	| Null	//空值类型
	| Time
	| []Any		//数组类型
	| bool
	| f32
	| f64
	| i64
	| int
	| map[string]Any	//字典类型
	| string
	| u64

可以调用Any对应的方法,把节点值转换为对应的数据类型:

pub fn (a Any) string()	string // 把节点值转换为sting类型
pub fn (a Any) int()	int
...
pub fn (a Any) array() []Any //转换为数组类型
pub fn (a Any) as_map() map[string]Any //转换为字典类型

toml注解

就像结构体的json注解那样,结构体也支持toml注解,实现结构体字段和toml字段的自定义

import toml

const toml_text = '# This TOML can reflect to a struct
name = "Tom"
age = 45
height = 1.97

birthday = 1980-04-23

strings = [
  "v matures",
  "like rings",
  "spread in the",
  "water"
]

bools = [true, false, true, true]

floats = [0.0, 1.0, 2.0, 3.0]

int_map = {"a" = 0, "b" = 1, "c" = 2, "d" = 3}

[bio]
text = "Tom has done many great things"
years_of_service = 5

[field_remap]
txt = "I am remapped"
uint64 = 100

[config]
data = [ 1, 2, 3 ]
levels = { "info" = 1, "warn" = 2, "critical" = 3 }
'

struct FieldRemap {
	text string [toml: 'txt'] //支持toml字段名自定义注解
	num  u64    [toml: 'uint64']
}

struct Bio {
	text             string
	years_of_service int
}

struct User {
	name     string
	age      int
	height   f64
	birthday toml.Date
	strings  []string
	bools    []bool
	floats   []f32
	int_map  map[string]int

	config toml.Any
mut:
	bio   Bio
	remap FieldRemap
}

fn main() {
	toml_doc := toml.parse_text(toml_text) or { panic(err) }

	mut user := toml_doc.reflect[User]()
	user.bio = toml_doc.value('bio').reflect[Bio]()
	user.remap = toml_doc.value('field_remap').reflect[FieldRemap]() //根据自定义toml字段名进行反射解析

	assert user.name == 'Tom'
	assert user.age == 45
	assert user.height == 1.97
	assert user.birthday.str() == '1980-04-23'
	assert user.strings == ['v matures', 'like rings', 'spread in the', 'water']
	assert user.bools == [true, false, true, true]
	assert user.floats == [f32(0.0), 1.0, 2.0, 3.0]
	assert user.int_map == {
		'a': 0
		'b': 1
		'c': 2
		'd': 3
	}
	assert user.bio.text == 'Tom has done many great things'
	assert user.bio.years_of_service == 5

	assert user.remap.text == 'I am remapped'
	assert user.remap.num == 100

	assert user.config.value('data[0]').int() == 1
	assert user.config.value('levels.warn').int() == 2
}

将toml转化为json

import toml.to
to.json(doc)

完整示例

import toml
import toml.to

const toml_text = '# This is a TOML document.

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00 # First class dates

[database]
server = "192.168.1.1"
ports = [ 8000, 8001, 8002 ]
connection_max = 5000
enabled = true

[servers]

  # Indentation (tabs and/or spaces) is allowed but not required
  [servers.alpha]
  ip = "10.0.0.1"
  dc = "eqdc10"

  [servers.beta]
  ip = "10.0.0.2"
  dc = "eqdc10"

[clients]
data = [ ["gamma", "delta"], [1, 2] ]

# Line breaks are OK when inside arrays
hosts = [
  "alpha",
  "omega"
]'

fn main() {
	doc := toml.parse_text(toml_text) or { panic(err) } //解析文本
	// doc := toml.parse_file("./conifg.toml") or { panic(err) } //解析文件
	title := doc.value('title').string()
	title2 := doc.value('title') as string
	owner := doc.value('owner') as map[string]toml.Any
	println('title: "$title"')
	println('title: "$title2"')
	println('owner: $owner')
	ip := doc.value('servers.alpha.ip').string() // value可以通过点号表示toml的层级
	println('Server IP: "$ip"')

	toml_json := to.json(doc) //转化为json格式
	println(toml_json)
}

最后更新于