gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

README.md (17026B)


      1 # go-toml v2
      2 
      3 Go library for the [TOML](https://toml.io/en/) format.
      4 
      5 This library supports [TOML v1.0.0](https://toml.io/en/v1.0.0).
      6 
      7 [🐞 Bug Reports](https://github.com/pelletier/go-toml/issues)
      8 
      9 [💬 Anything else](https://github.com/pelletier/go-toml/discussions)
     10 
     11 ## Documentation
     12 
     13 Full API, examples, and implementation notes are available in the Go
     14 documentation.
     15 
     16 [![Go Reference](https://pkg.go.dev/badge/github.com/pelletier/go-toml/v2.svg)](https://pkg.go.dev/github.com/pelletier/go-toml/v2)
     17 
     18 ## Import
     19 
     20 ```go
     21 import "github.com/pelletier/go-toml/v2"
     22 ```
     23 
     24 See [Modules](#Modules).
     25 
     26 ## Features
     27 
     28 ### Stdlib behavior
     29 
     30 As much as possible, this library is designed to behave similarly as the
     31 standard library's `encoding/json`.
     32 
     33 ### Performance
     34 
     35 While go-toml favors usability, it is written with performance in mind. Most
     36 operations should not be shockingly slow. See [benchmarks](#benchmarks).
     37 
     38 ### Strict mode
     39 
     40 `Decoder` can be set to "strict mode", which makes it error when some parts of
     41 the TOML document was not present in the target structure. This is a great way
     42 to check for typos. [See example in the documentation][strict].
     43 
     44 [strict]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#example-Decoder.DisallowUnknownFields
     45 
     46 ### Contextualized errors
     47 
     48 When most decoding errors occur, go-toml returns [`DecodeError`][decode-err]),
     49 which contains a human readable contextualized version of the error. For
     50 example:
     51 
     52 ```
     53 2| key1 = "value1"
     54 3| key2 = "missing2"
     55  | ~~~~ missing field
     56 4| key3 = "missing3"
     57 5| key4 = "value4"
     58 ```
     59 
     60 [decode-err]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#DecodeError
     61 
     62 ### Local date and time support
     63 
     64 TOML supports native [local date/times][ldt]. It allows to represent a given
     65 date, time, or date-time without relation to a timezone or offset. To support
     66 this use-case, go-toml provides [`LocalDate`][tld], [`LocalTime`][tlt], and
     67 [`LocalDateTime`][tldt]. Those types can be transformed to and from `time.Time`,
     68 making them convenient yet unambiguous structures for their respective TOML
     69 representation.
     70 
     71 [ldt]: https://toml.io/en/v1.0.0#local-date-time
     72 [tld]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDate
     73 [tlt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalTime
     74 [tldt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDateTime
     75 
     76 ## Getting started
     77 
     78 Given the following struct, let's see how to read it and write it as TOML:
     79 
     80 ```go
     81 type MyConfig struct {
     82       Version int
     83       Name    string
     84       Tags    []string
     85 }
     86 ```
     87 
     88 ### Unmarshaling
     89 
     90 [`Unmarshal`][unmarshal] reads a TOML document and fills a Go structure with its
     91 content. For example:
     92 
     93 ```go
     94 doc := `
     95 version = 2
     96 name = "go-toml"
     97 tags = ["go", "toml"]
     98 `
     99 
    100 var cfg MyConfig
    101 err := toml.Unmarshal([]byte(doc), &cfg)
    102 if err != nil {
    103       panic(err)
    104 }
    105 fmt.Println("version:", cfg.Version)
    106 fmt.Println("name:", cfg.Name)
    107 fmt.Println("tags:", cfg.Tags)
    108 
    109 // Output:
    110 // version: 2
    111 // name: go-toml
    112 // tags: [go toml]
    113 ```
    114 
    115 [unmarshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Unmarshal
    116 
    117 ### Marshaling
    118 
    119 [`Marshal`][marshal] is the opposite of Unmarshal: it represents a Go structure
    120 as a TOML document:
    121 
    122 ```go
    123 cfg := MyConfig{
    124       Version: 2,
    125       Name:    "go-toml",
    126       Tags:    []string{"go", "toml"},
    127 }
    128 
    129 b, err := toml.Marshal(cfg)
    130 if err != nil {
    131       panic(err)
    132 }
    133 fmt.Println(string(b))
    134 
    135 // Output:
    136 // Version = 2
    137 // Name = 'go-toml'
    138 // Tags = ['go', 'toml']
    139 ```
    140 
    141 [marshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Marshal
    142 
    143 ## Unstable API
    144 
    145 This API does not yet follow the backward compatibility guarantees of this
    146 library. They provide early access to features that may have rough edges or an
    147 API subject to change.
    148 
    149 ### Parser
    150 
    151 Parser is the unstable API that allows iterative parsing of a TOML document at
    152 the AST level. See https://pkg.go.dev/github.com/pelletier/go-toml/v2/unstable.
    153 
    154 ## Benchmarks
    155 
    156 Execution time speedup compared to other Go TOML libraries:
    157 
    158 <table>
    159     <thead>
    160         <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
    161     </thead>
    162     <tbody>
    163         <tr><td>Marshal/HugoFrontMatter-2</td><td>1.9x</td><td>1.9x</td></tr>
    164         <tr><td>Marshal/ReferenceFile/map-2</td><td>1.7x</td><td>1.8x</td></tr>
    165         <tr><td>Marshal/ReferenceFile/struct-2</td><td>2.2x</td><td>2.5x</td></tr>
    166         <tr><td>Unmarshal/HugoFrontMatter-2</td><td>2.9x</td><td>2.9x</td></tr>
    167         <tr><td>Unmarshal/ReferenceFile/map-2</td><td>2.6x</td><td>2.9x</td></tr>
    168         <tr><td>Unmarshal/ReferenceFile/struct-2</td><td>4.4x</td><td>5.3x</td></tr>
    169      </tbody>
    170 </table>
    171 <details><summary>See more</summary>
    172 <p>The table above has the results of the most common use-cases. The table below
    173 contains the results of all benchmarks, including unrealistic ones. It is
    174 provided for completeness.</p>
    175 
    176 <table>
    177     <thead>
    178         <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
    179     </thead>
    180     <tbody>
    181         <tr><td>Marshal/SimpleDocument/map-2</td><td>1.8x</td><td>2.9x</td></tr>
    182         <tr><td>Marshal/SimpleDocument/struct-2</td><td>2.7x</td><td>4.2x</td></tr>
    183         <tr><td>Unmarshal/SimpleDocument/map-2</td><td>4.5x</td><td>3.1x</td></tr>
    184         <tr><td>Unmarshal/SimpleDocument/struct-2</td><td>6.2x</td><td>3.9x</td></tr>
    185         <tr><td>UnmarshalDataset/example-2</td><td>3.1x</td><td>3.5x</td></tr>
    186         <tr><td>UnmarshalDataset/code-2</td><td>2.3x</td><td>3.1x</td></tr>
    187         <tr><td>UnmarshalDataset/twitter-2</td><td>2.5x</td><td>2.6x</td></tr>
    188         <tr><td>UnmarshalDataset/citm_catalog-2</td><td>2.1x</td><td>2.2x</td></tr>
    189         <tr><td>UnmarshalDataset/canada-2</td><td>1.6x</td><td>1.3x</td></tr>
    190         <tr><td>UnmarshalDataset/config-2</td><td>4.3x</td><td>3.2x</td></tr>
    191         <tr><td>[Geo mean]</td><td>2.7x</td><td>2.8x</td></tr>
    192      </tbody>
    193 </table>
    194 <p>This table can be generated with <code>./ci.sh benchmark -a -html</code>.</p>
    195 </details>
    196 
    197 ## Modules
    198 
    199 go-toml uses Go's standard modules system.
    200 
    201 Installation instructions:
    202 
    203 - Go ≥ 1.16: Nothing to do. Use the import in your code. The `go` command deals
    204   with it automatically.
    205 - Go ≥ 1.13: `GO111MODULE=on go get github.com/pelletier/go-toml/v2`.
    206 
    207 In case of trouble: [Go Modules FAQ][mod-faq].
    208 
    209 [mod-faq]: https://github.com/golang/go/wiki/Modules#why-does-installing-a-tool-via-go-get-fail-with-error-cannot-find-main-module
    210 
    211 ## Tools
    212 
    213 Go-toml provides three handy command line tools:
    214 
    215  * `tomljson`: Reads a TOML file and outputs its JSON representation.
    216 
    217     ```
    218     $ go install github.com/pelletier/go-toml/v2/cmd/tomljson@latest
    219     $ tomljson --help
    220     ```
    221 
    222  * `jsontoml`: Reads a JSON file and outputs a TOML representation.
    223 
    224     ```
    225     $ go install github.com/pelletier/go-toml/v2/cmd/jsontoml@latest
    226     $ jsontoml --help
    227     ```
    228 
    229  * `tomll`: Lints and reformats a TOML file.
    230 
    231     ```
    232     $ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest
    233     $ tomll --help
    234     ```
    235 
    236 ### Docker image
    237 
    238 Those tools are also available as a [Docker image][docker]. For example, to use
    239 `tomljson`:
    240 
    241 ```
    242 docker run -i ghcr.io/pelletier/go-toml:v2 tomljson < example.toml
    243 ```
    244 
    245 Multiple versions are availble on [ghcr.io][docker].
    246 
    247 [docker]: https://github.com/pelletier/go-toml/pkgs/container/go-toml
    248 
    249 ## Migrating from v1
    250 
    251 This section describes the differences between v1 and v2, with some pointers on
    252 how to get the original behavior when possible.
    253 
    254 ### Decoding / Unmarshal
    255 
    256 #### Automatic field name guessing
    257 
    258 When unmarshaling to a struct, if a key in the TOML document does not exactly
    259 match the name of a struct field or any of the `toml`-tagged field, v1 tries
    260 multiple variations of the key ([code][v1-keys]).
    261 
    262 V2 instead does a case-insensitive matching, like `encoding/json`.
    263 
    264 This could impact you if you are relying on casing to differentiate two fields,
    265 and one of them is a not using the `toml` struct tag. The recommended solution
    266 is to be specific about tag names for those fields using the `toml` struct tag.
    267 
    268 [v1-keys]: https://github.com/pelletier/go-toml/blob/a2e52561804c6cd9392ebf0048ca64fe4af67a43/marshal.go#L775-L781
    269 
    270 #### Ignore preexisting value in interface
    271 
    272 When decoding into a non-nil `interface{}`, go-toml v1 uses the type of the
    273 element in the interface to decode the object. For example:
    274 
    275 ```go
    276 type inner struct {
    277   B interface{}
    278 }
    279 type doc struct {
    280   A interface{}
    281 }
    282 
    283 d := doc{
    284   A: inner{
    285     B: "Before",
    286   },
    287 }
    288 
    289 data := `
    290 [A]
    291 B = "After"
    292 `
    293 
    294 toml.Unmarshal([]byte(data), &d)
    295 fmt.Printf("toml v1: %#v\n", d)
    296 
    297 // toml v1: main.doc{A:main.inner{B:"After"}}
    298 ```
    299 
    300 In this case, field `A` is of type `interface{}`, containing a `inner` struct.
    301 V1 sees that type and uses it when decoding the object.
    302 
    303 When decoding an object into an `interface{}`, V2 instead disregards whatever
    304 value the `interface{}` may contain and replaces it with a
    305 `map[string]interface{}`. With the same data structure as above, here is what
    306 the result looks like:
    307 
    308 ```go
    309 toml.Unmarshal([]byte(data), &d)
    310 fmt.Printf("toml v2: %#v\n", d)
    311 
    312 // toml v2: main.doc{A:map[string]interface {}{"B":"After"}}
    313 ```
    314 
    315 This is to match `encoding/json`'s behavior. There is no way to make the v2
    316 decoder behave like v1.
    317 
    318 #### Values out of array bounds ignored
    319 
    320 When decoding into an array, v1 returns an error when the number of elements
    321 contained in the doc is superior to the capacity of the array. For example:
    322 
    323 ```go
    324 type doc struct {
    325   A [2]string
    326 }
    327 d := doc{}
    328 err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
    329 fmt.Println(err)
    330 
    331 // (1, 1): unmarshal: TOML array length (3) exceeds destination array length (2)
    332 ```
    333 
    334 In the same situation, v2 ignores the last value:
    335 
    336 ```go
    337 err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
    338 fmt.Println("err:", err, "d:", d)
    339 // err: <nil> d: {[one two]}
    340 ```
    341 
    342 This is to match `encoding/json`'s behavior. There is no way to make the v2
    343 decoder behave like v1.
    344 
    345 #### Support for `toml.Unmarshaler` has been dropped
    346 
    347 This method was not widely used, poorly defined, and added a lot of complexity.
    348 A similar effect can be achieved by implementing the `encoding.TextUnmarshaler`
    349 interface and use strings.
    350 
    351 #### Support for `default` struct tag has been dropped
    352 
    353 This feature adds complexity and a poorly defined API for an effect that can be
    354 accomplished outside of the library.
    355 
    356 It does not seem like other format parsers in Go support that feature (the
    357 project referenced in the original ticket #202 has not been updated since 2017).
    358 Given that go-toml v2 should not touch values not in the document, the same
    359 effect can be achieved by pre-filling the struct with defaults (libraries like
    360 [go-defaults][go-defaults] can help). Also, string representation is not well
    361 defined for all types: it creates issues like #278.
    362 
    363 The recommended replacement is pre-filling the struct before unmarshaling.
    364 
    365 [go-defaults]: https://github.com/mcuadros/go-defaults
    366 
    367 #### `toml.Tree` replacement
    368 
    369 This structure was the initial attempt at providing a document model for
    370 go-toml. It allows manipulating the structure of any document, encoding and
    371 decoding from their TOML representation. While a more robust feature was
    372 initially planned in go-toml v2, this has been ultimately [removed from
    373 scope][nodoc] of this library, with no plan to add it back at the moment. The
    374 closest equivalent at the moment would be to unmarshal into an `interface{}` and
    375 use type assertions and/or reflection to manipulate the arbitrary
    376 structure. However this would fall short of providing all of the TOML features
    377 such as adding comments and be specific about whitespace.
    378 
    379 
    380 #### `toml.Position` are not retrievable anymore
    381 
    382 The API for retrieving the position (line, column) of a specific TOML element do
    383 not exist anymore. This was done to minimize the amount of concepts introduced
    384 by the library (query path), and avoid the performance hit related to storing
    385 positions in the absence of a document model, for a feature that seemed to have
    386 little use. Errors however have gained more detailed position
    387 information. Position retrieval seems better fitted for a document model, which
    388 has been [removed from the scope][nodoc] of go-toml v2 at the moment.
    389 
    390 ### Encoding / Marshal
    391 
    392 #### Default struct fields order
    393 
    394 V1 emits struct fields order alphabetically by default. V2 struct fields are
    395 emitted in order they are defined. For example:
    396 
    397 ```go
    398 type S struct {
    399 	B string
    400 	A string
    401 }
    402 
    403 data := S{
    404 	B: "B",
    405 	A: "A",
    406 }
    407 
    408 b, _ := tomlv1.Marshal(data)
    409 fmt.Println("v1:\n" + string(b))
    410 
    411 b, _ = tomlv2.Marshal(data)
    412 fmt.Println("v2:\n" + string(b))
    413 
    414 // Output:
    415 // v1:
    416 // A = "A"
    417 // B = "B"
    418 
    419 // v2:
    420 // B = 'B'
    421 // A = 'A'
    422 ```
    423 
    424 There is no way to make v2 encoder behave like v1. A workaround could be to
    425 manually sort the fields alphabetically in the struct definition, or generate
    426 struct types using `reflect.StructOf`.
    427 
    428 #### No indentation by default
    429 
    430 V1 automatically indents content of tables by default. V2 does not. However the
    431 same behavior can be obtained using [`Encoder.SetIndentTables`][sit]. For example:
    432 
    433 ```go
    434 data := map[string]interface{}{
    435 	"table": map[string]string{
    436 		"key": "value",
    437 	},
    438 }
    439 
    440 b, _ := tomlv1.Marshal(data)
    441 fmt.Println("v1:\n" + string(b))
    442 
    443 b, _ = tomlv2.Marshal(data)
    444 fmt.Println("v2:\n" + string(b))
    445 
    446 buf := bytes.Buffer{}
    447 enc := tomlv2.NewEncoder(&buf)
    448 enc.SetIndentTables(true)
    449 enc.Encode(data)
    450 fmt.Println("v2 Encoder:\n" + string(buf.Bytes()))
    451 
    452 // Output:
    453 // v1:
    454 //
    455 // [table]
    456 //   key = "value"
    457 //
    458 // v2:
    459 // [table]
    460 // key = 'value'
    461 //
    462 //
    463 // v2 Encoder:
    464 // [table]
    465 //   key = 'value'
    466 ```
    467 
    468 [sit]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Encoder.SetIndentTables
    469 
    470 #### Keys and strings are single quoted
    471 
    472 V1 always uses double quotes (`"`) around strings and keys that cannot be
    473 represented bare (unquoted). V2 uses single quotes instead by default (`'`),
    474 unless a character cannot be represented, then falls back to double quotes. As a
    475 result of this change, `Encoder.QuoteMapKeys` has been removed, as it is not
    476 useful anymore.
    477 
    478 There is no way to make v2 encoder behave like v1.
    479 
    480 #### `TextMarshaler` emits as a string, not TOML
    481 
    482 Types that implement [`encoding.TextMarshaler`][tm] can emit arbitrary TOML in
    483 v1. The encoder would append the result to the output directly. In v2 the result
    484 is wrapped in a string. As a result, this interface cannot be implemented by the
    485 root object.
    486 
    487 There is no way to make v2 encoder behave like v1.
    488 
    489 [tm]: https://golang.org/pkg/encoding/#TextMarshaler
    490 
    491 #### `Encoder.CompactComments` has been removed
    492 
    493 Emitting compact comments is now the default behavior of go-toml. This option
    494 is not necessary anymore.
    495 
    496 #### Struct tags have been merged
    497 
    498 V1 used to provide multiple struct tags: `comment`, `commented`, `multiline`,
    499 `toml`, and `omitempty`. To behave more like the standard library, v2 has merged
    500 `toml`, `multiline`, and `omitempty`. For example:
    501 
    502 ```go
    503 type doc struct {
    504 	// v1
    505 	F string `toml:"field" multiline:"true" omitempty:"true"`
    506 	// v2
    507 	F string `toml:"field,multiline,omitempty"`
    508 }
    509 ```
    510 
    511 Has a result, the `Encoder.SetTag*` methods have been removed, as there is just
    512 one tag now.
    513 
    514 
    515 #### `commented` tag has been removed
    516 
    517 There is no replacement for the `commented` tag. This feature would be better
    518 suited in a proper document model for go-toml v2, which has been [cut from
    519 scope][nodoc] at the moment.
    520 
    521 #### `Encoder.ArraysWithOneElementPerLine` has been renamed
    522 
    523 The new name is `Encoder.SetArraysMultiline`. The behavior should be the same.
    524 
    525 #### `Encoder.Indentation` has been renamed
    526 
    527 The new name is `Encoder.SetIndentSymbol`. The behavior should be the same.
    528 
    529 
    530 #### Embedded structs behave like stdlib
    531 
    532 V1 defaults to merging embedded struct fields into the embedding struct. This
    533 behavior was unexpected because it does not follow the standard library. To
    534 avoid breaking backward compatibility, the `Encoder.PromoteAnonymous` method was
    535 added to make the encoder behave correctly. Given backward compatibility is not
    536 a problem anymore, v2 does the right thing by default: it follows the behavior
    537 of `encoding/json`. `Encoder.PromoteAnonymous` has been removed.
    538 
    539 [nodoc]: https://github.com/pelletier/go-toml/discussions/506#discussioncomment-1526038
    540 
    541 ### `query`
    542 
    543 go-toml v1 provided the [`go-toml/query`][query] package. It allowed to run
    544 JSONPath-style queries on TOML files. This feature is not available in v2. For a
    545 replacement, check out [dasel][dasel].
    546 
    547 This package has been removed because it was essentially not supported anymore
    548 (last commit May 2020), increased the complexity of the code base, and more
    549 complete solutions exist out there.
    550 
    551 [query]: https://github.com/pelletier/go-toml/tree/f99d6bbca119636aeafcf351ee52b3d202782627/query
    552 [dasel]: https://github.com/TomWright/dasel
    553 
    554 ## Versioning
    555 
    556 Go-toml follows [Semantic Versioning](https://semver.org). The supported version
    557 of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of
    558 this document. The last two major versions of Go are supported
    559 (see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)).
    560 
    561 ## License
    562 
    563 The MIT License (MIT). Read [LICENSE](LICENSE).