Skip to content

Commit 77d0dc9

Browse files
authored
Unmarshal comments using hjson.Node (#54)
1 parent f473b94 commit 77d0dc9

File tree

10 files changed

+1728
-172
lines changed

10 files changed

+1728
-172
lines changed

.github/workflows/test.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ jobs:
88
matrix:
99
os: [ubuntu-latest, macos-latest, windows-latest]
1010
steps:
11-
- uses: actions/checkout@v2
11+
- uses: actions/checkout@v3
1212
- run: go version
1313
- run: go test -v
1414
- run: |
1515
cd hjson-cli
16-
go install -i
16+
go install

README.md

+85-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ Options:
6262
-j Output as formatted JSON.
6363
-omitRootBraces
6464
Omit braces at the root.
65+
-preserveKeyOrder
66+
Preserve key order in objects/maps.
6567
-quoteAlways
6668
Always quote string values.
6769
-v
@@ -184,7 +186,7 @@ func main() {
184186

185187
## Comments on struct fields
186188

187-
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.
189+
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.
188190

189191
```go
190192

@@ -229,6 +231,88 @@ Output:
229231
}
230232
```
231233

234+
## Read and write comments
235+
236+
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.
237+
238+
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:
239+
240+
* `nil` (no type)
241+
* `float64`   (if *UseJSONNumber* == `false`)
242+
* *json.Number*   (if *UseJSONNumber* == `true`)
243+
* `string`
244+
* `bool`
245+
* `[]interface{}`
246+
* **hjson.OrderedMap*
247+
248+
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.
249+
250+
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`.
251+
252+
```go
253+
254+
package main
255+
256+
import (
257+
"fmt"
258+
259+
"github.com/hjson/hjson-go/v4"
260+
)
261+
262+
func main() {
263+
// Now let's look at decoding Hjson data into hjson.Node.
264+
sampleText := []byte(`
265+
{
266+
# specify rate in requests/second
267+
rate: 1000
268+
array:
269+
[
270+
foo
271+
bar
272+
]
273+
}`)
274+
275+
var node hjson.Node
276+
if err := hjson.Unmarshal(sampleText, &node); err != nil {
277+
panic(err)
278+
}
279+
280+
node.NK("array").Cm.Before = ` # please specify an array
281+
`
282+
283+
if _, _, err := node.NKC("subMap").SetKey("subVal", 1); err != nil {
284+
panic(err)
285+
}
286+
287+
outBytes, err := hjson.Marshal(node)
288+
if err != nil {
289+
panic(err)
290+
}
291+
292+
fmt.Println(string(outBytes))
293+
}
294+
```
295+
296+
Output:
297+
298+
```
299+
300+
{
301+
# specify rate in requests/second
302+
rate: 1000
303+
# please specify an array
304+
array:
305+
[
306+
foo
307+
bar
308+
]
309+
subMap: {
310+
subVal: 1
311+
}
312+
}
313+
```
314+
315+
232316
## Type ambiguity
233317

234318
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.

0 commit comments

Comments
 (0)