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
Can't decode into map[string]interface{} #291
Comments
Hi @brikis98, At the moment there is no default decoding into Decoding into The most direct conversion of an HCL number is a So far in situations where we've found decoding implementation details leaking into exported structs we've avoided it by using temporary structs just for decoding, and then populating the exported struct before returning. This also gives an opportunity to do any additional validations that HCL's schema cannot represent: func decodeExampleBlock(block *hcl.Block) (*Example, hcl.Diagnostics) {
type DecodeExample struct {
Foo string `hcl:"foo,attr"`
Bar cty.Value `hcl:"bar,attr"`
}
var raw DecodeExample
diags := gohcl.DecodeBody(block.Body, nil, &raw)
if diags.HasErrors() {
return diags
}
ret := &Example{
Foo: raw.Foo,
Bar: map[string]interface{},
}
// then use your own logic to map cty into the map[string]interface{}
// using whatever mapping rules make sense for your application.
return ret, diags
} However, as long as we can define it in a way that doesn't silently lose information I think having a default decoding into I don't expect I'll have time to work on this in the near future since there's lots of Terraform-side work keeping me busy right now. If a short-term solution is needed, I guess I'd suggest using the local decoding struct pattern I described above and then doing the final step by actually serializing the |
Understood, thanks for the detailed answer! |
@apparentlymart Hi! I am a HUG organizer and contributor to a number of HashiCorp products. I am very interested in programming languages and would love to start contributing to hcl2! Let me know if this issue or any others would be a good place to start helping out :) |
how can terraform decode the terraform files? The structure is not known upfront so they cant create structs. I also want to parse a user provided hcl file where I dont know whats written inside, I am not sure how I can do this. For example using |
Hi @bluebrown, Terraform's configuration decoder is subject to the same requirement of providing a schema in order to decode a HCL body. There is nothing in the Terraform language that cannot be decoded using the HCL API, although Terraform does make use of some more advanced HCL API features that are not reachable using There is no way to decode blocks without providing a schema for those blocks, because it is the schema which allows resolving the inherent ambiguity in the JSON serialization of the HCL infoset, where HCL arguments and blocks are both represented as properties of a JSON object. When you are designing an HCL-based language you must decide the block structure as part of the language design and encode it into your program. |
Thanks ,@apparentlymart, I as a user can decide in which TF file I put which blocks, or not? I can make one full of variables and another one containing a server resource or something like that. At that point, I may have definitions but I don't know which one is in which file, so how could I decode it? |
If your goal is to parse a Terraform configuration then that is more of a Terraform question than it is an HCL question. HCL is just a collection of syntax primitives for building languages with, and so there's a lot more to the Terraform language than just HCL alone: you'd need to reimplement its schema and the schema of any providers that would normally be involved in processing that configuration. Terraform-specific questions are not really on topic for this repository, which is about the generic HCL library rather than any particular application using it, but if you ask in Terraform's community forum and say some more about what your goals are then someone there (possibly me!) may be able to offer some concrete suggestions on how to achieve your goal. |
Just a +1 - I think may break round-tripping certain Nomad jobspecs (since Nomad Job Tasks contain a |
I have almost the same question as @bluebrown and haven't been able to find (even remotely) an answer pointing me in the right direction. My usecase is similar I need to be able to parse hcl that is essentially freeform / schemaless into something that I can work with get values from within go. Now, within that massive space of possibilties my usecase is a narrow scope. A good example of this is locals {
some_list = []
some_map = {k="v"}
some_nested = [{}]
some_bool = true
some_string = "yolo"
} This is the type of struct I'd just like to "glob" in. There are two specific problems, using terraform as an example, assuming it had a .hcl extension, I need to first find the locals which could be in any .tf file and I need to read them in in some way that allows me access the values similar to |
HCL is not designed for "schemaless" languages. The evaluation model relies on schema to resolve ambiguities such as those in the JSON syntax.
This sort of unusual decoding strategy is harder to express with the type Example struct {
Attributes hcl.Attributes `hcl:",remain"`
} If you decode into a valid of the above type, The main thing to recognize here is that treating attributes in a body as dynamic is itself still a static schema-like decision. HCL does not provide any way to just "decode the whole thing and see what happens" because the HCL infoset is a superset of the Go type system and so I also want to restate what I said above: Terraform does not use |
@apparentlymart massive thanks, not only did you help to solve my problem you changed my thinking of the problem almost entirely. |
I've been experimenting with the
hcl2
code for use with Terragrunt, and so far, things have been going well. The parser is intuitive, the error messages are helpful, and the first-class support for expressions, functions, variables, etc is great! A big improvement over the original hcl code 👍The one issue I'm hitting is when trying to use
Decode
function with the following struct:I try to decode it as follows:
I get the following error:
The
Bar
field of theExample
struct is intentionally amap[string]interface{}
because this is data that is user provided, and I have no way of knowing the types of the values; they could be strings, ints, bools, slices, maps, etc. I could parse this as ablock
and use theremain
metadata to get backhcl.Body
, but that requires changing theExample
struct in a way that (a) is backwards incompatible, (b) leaks the underlying implementation details, and (c) is hard to use.Is there any way to decode into a
map[string]interface{}
directly?The text was updated successfully, but these errors were encountered: