Skip to content

Commit

Permalink
Unmarshal comments using hjson.Node (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
trobro authored Dec 11, 2022
1 parent f473b94 commit 77d0dc9
Show file tree
Hide file tree
Showing 10 changed files with 1,728 additions and 172 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- run: go version
- run: go test -v
- run: |
cd hjson-cli
go install -i
go install
86 changes: 85 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ Options:
-j Output as formatted JSON.
-omitRootBraces
Omit braces at the root.
-preserveKeyOrder
Preserve key order in objects/maps.
-quoteAlways
Always quote string values.
-v
Expand Down Expand Up @@ -184,7 +186,7 @@ func main() {

## Comments on struct fields

By using key `comment` in struct field tags you can specify comments to be written on one or more lines preceding the struct field in the Hjson output.
By using key `comment` in struct field tags you can specify comments to be written on one or more lines preceding the struct field in the Hjson output. Another way to output comments is to use *hjson.Node* structs, more on than later.

```go

Expand Down Expand Up @@ -229,6 +231,88 @@ Output:
}
```

## Read and write comments

The only way to read comments from Hjson input is to use a destination variable of type *hjson.Node* or **hjson.Node*. The *hjson.Node* must be the root destination, it won't work if you create a field of type *hjson.Node* in some other struct and use that struct as destination. An *hjson.Node* struct is simply a wrapper for a value and comments stored in an *hjson.Comments* struct. It also has several convenience functions, for example *AtIndex()* or *SetKey()* that can be used when you know that the node contains a value of type `[]interface{}` or **hjson.OrderedMap*. All of the elements in `[]interface{}` or **hjson.OrderedMap* will be of type **hjson.Node* in trees created by *hjson.Unmarshal*, but the *hjson.Node* convenience functions unpack the actual values from them.

When *hjson.Node* or **hjson.Node* is used as destination for Hjson unmarshal the output will be a tree of **hjson.Node* where all of the values contained in tree nodes will be of these types:

* `nil` (no type)
* `float64`   (if *UseJSONNumber* == `false`)
* *json.Number*   (if *UseJSONNumber* == `true`)
* `string`
* `bool`
* `[]interface{}`
* **hjson.OrderedMap*

These are just the types used by Hjson unmarshal and the convenience functions, you are free to assign any type of values to nodes in your own code.

The comments will contain all whitespace chars too (including line feeds) so that an Hjson document can be read and written without altering the layout. This can be disabled by setting the decoding option *WhitespaceAsComments* to `false`.

```go

package main

import (
"fmt"

"github.com/hjson/hjson-go/v4"
)

func main() {
// Now let's look at decoding Hjson data into hjson.Node.
sampleText := []byte(`
{
# specify rate in requests/second
rate: 1000
array:
[
foo
bar
]
}`)

var node hjson.Node
if err := hjson.Unmarshal(sampleText, &node); err != nil {
panic(err)
}

node.NK("array").Cm.Before = ` # please specify an array
`

if _, _, err := node.NKC("subMap").SetKey("subVal", 1); err != nil {
panic(err)
}

outBytes, err := hjson.Marshal(node)
if err != nil {
panic(err)
}

fmt.Println(string(outBytes))
}
```

Output:

```
{
# specify rate in requests/second
rate: 1000
# please specify an array
array:
[
foo
bar
]
subMap: {
subVal: 1
}
}
```


## Type ambiguity

Hjson allows quoteless strings. But if a value is a valid number, boolean or `null` then it will be unmarshalled into that type instead of a string when unmarshalling into `interface{}`. This can lead to unintended consequences if the creator of an Hjson file meant to write a string but didn't think of that the quoteless string they wrote also was a valid number.
Expand Down
Loading

0 comments on commit 77d0dc9

Please sign in to comment.