-
Notifications
You must be signed in to change notification settings - Fork 591
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Article example doesn't work #193
Comments
Hi @scottf This is the way most parsing libraries work in go - they assume the field is named the same. If you are using underscore names, you'll need to label the struct fields as so: type Config struct {
Region string
AccessKey string `hcl:"access_key"`
SecretKey string `hcl:"secret_key"`
Bucket string
Directories []DirectoryConfig
} |
Thanks for the response, that works, sorta. So I continued to try to understand and coded something up. package main
import (
"github.com/hashicorp/hcl"
"fmt"
)
type Foo struct {
Region string
CamelCase string `hcl:"camel_case"`
Bars []Bar `hcl:"bar"`
}
type Bar struct {
Name string
CamelBaz string `hcl:"camel_baz"`
}
func main() {
fmt.Println(data, "\n")
cfg := &Foo{}
err := hcl.Decode(cfg, data)
if err != nil {
fmt.Println("Err", err)
} else {
fmt.Println(fmt.Sprintf("Foo: Region='%s' CamelCase='%s' Bars? %d", cfg.Region, cfg.CamelCase, len(cfg.Bars)))
for _,bar := range cfg.Bars {
fmt.Println(fmt.Sprintf(" Bar: Name='%s' Baz='%s'", bar.Name, bar.CamelBaz))
}
}
}
var data = "region = \"us-west-2\"\n" +
"camel_case = \"blah\"\n" +
"\n" +
"bar \"nameA\" {\n" +
" camel_baz = \"bazA\"\n" +
"}\n" +
"bar \"nameB\" {\n" +
" name = \"nameBprime\"\n" +
" camel_baz = \"bazB\"\n" +
"}\n" +
"bar {\n" +
" name = \"nameCprime\"\n" +
" camel_baz = \"bazC\"\n" +
"}" The output is this:
|
Hey @scottf Thank you for your reply. It's probably best if you print out the JSON instead of using a custom dump function, as it'll be clearer what the library is doing: package main
import (
"encoding/json"
"fmt"
"github.com/hashicorp/hcl"
)
type Foo struct {
Region string
CamelCase string `hcl:"camel_case"`
Bars []Bar `hcl:"bar"`
}
type Bar struct {
Name string
CamelBaz string `hcl:"camel_baz"`
}
func main() {
var cfg Foo
if err := hcl.Decode(&cfg, data); err != nil {
panic(err)
}
b, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", b)
}
var data = `
region = "us-west-2"
camel_case = "blah"
bar "nameA" {
camel_baz = "bazA"
}
bar "nameB" {
name = "nameBprime"
camel_baz = "bazB"
}
bar {
name = "nameCprime"
camel_baz = "bazC"
}
` In short, because you did not provide a string to the third bar function, there's no way to safely merge that data, so it's split into two objects. If you supply a name to the third bar, you get three bars as expected. Since you're "naming" the bars, you probably want to decode into a {
"Region": "us-west-2",
"CamelCase": "blah",
"Bars": {
"nameA": {
"Name": "",
"CamelBaz": "bazA"
},
"nameB": {
"Name": "nameBprime",
"CamelBaz": "bazB"
},
"nameC": {
"Name": "nameCprime",
"CamelBaz": "bazC"
}
}
} |
The json helps clear it up and that's a much easier way to put the data in the code. It still doesn't work as I expected for that data, there are still 4 bars. As for the It seems that you must name (tag?) the object, but the name can be empty. bar "" {
name = "nameAprime"
camel_baz = "bazA"
}
bar "" {
name = "nameBprime"
camel_baz = "bazB"
} The other two formats don't work at all, I tested them individually. Thanks for your help. |
Hi @scottf You're reading an article dated 2015, so I'm not surprised there are differences now. HCL was just a baby in 2015 and has since matured greatly. Can you tell me what your expected output is (in JSON), and I can help you write the equivalent HCL? |
update with massive edit. Hi @scottf - I found the terraform HCL doco to be useful. https://www.terraform.io/docs/configuration/syntax.html Also this function: just dump in your HCL file and it pops out the equiv JSON func MustDecode(config string) {
var obj interface{}
if err := hcl.Decode(&obj, config); err != nil {
log.Printf("Unable to decode: %s", err)
}
out, err := json.MarshalIndent(obj, "", " ")
if err != nil {
log.Fatalf("Marshal fail: %s", err)
}
fmt.Println(string(out))
} So this works "as expected" filter {
include = "*"
}
filter {
include = "*.png"
} Here's the JSON {
"filter": [
{
"include": "*"
},
{
"include": "*.png"
}
]
} great! Now let's nest it root filter {
include = "*"
}
root filter {
include = "*.png"
} and the json is... {
"root": [
{
"filter": [
{
"include": "*"
}
]
},
{
"filter": [
{
"include": "*.png"
}
]
}
]
} Since the root object automatically makes lists (even with same name), these two stanza do not get merged, and are completely separate objects. Hope this helps (round 3) n |
Author wrote an article some time ago:
https://jen20.com/2015/09/07/using-hcl-part-1.html
Granted maybe there is stuff missing from the article like configuration. Are there ANY docs for this library?
Expected behavior
It works like it says in the article
Actual behavior
The data is only populated when words are not camel cased.
`&{us-west-2 backups []}'
Steps to reproduce
Here is my full code:
The text was updated successfully, but these errors were encountered: