Hjson for Go

hjson-go

Build Status Go Pkg Go Report Card coverage godoc

Hjson Intro

{
  # specify rate in requests/second (because comments are helpful!)
  rate: 1000

  // prefer c-style comments?
  /* feeling old fashioned? */

  # did you notice that rate doesn't need quotes?
  hey: look ma, no quotes for strings either!

  # best of all
  notice: []
  anything: ?

  # yes, commas are optional!
}

The Go implementation of Hjson is based on hjson-js. For other platforms see hjson.github.io.

Install

Make sure you have a working Go environment. See the install instructions.

  1. Get the sources
$ go get -u github.com/hjson/hjson-go
  1. Build the hjson-cli commandline tool (optional)
$ cd $(go env GOPATH)/src/github.com/hjson/hjson-go/hjson-cli && go install
$ hjson-cli --version

Usage as command line tool

usage: hjson-cli [OPTIONS] [INPUT]
hjson can be used to convert JSON from/to Hjson.

hjson will read the given JSON/Hjson input file or read from stdin.

Options:
  -allowMinusZero
      Allow -0.
  -bracesSameLine
      Print braces on the same line.
  -c  Output as JSON.
  -h  Show this screen.
  -indentBy string
      The indent string. (default "  ")
  -j  Output as formatted JSON.
  -omitRootBraces
      Omit braces at the root.
  -quoteAlways
      Always quote string values.

Sample:

  • run hjson-cli test.json > test.hjson to convert to Hjson
  • run hjson-cli -j test.hjson > test.json to convert to JSON

Usage as a GO library

package main

import (
  "github.com/hjson/hjson-go"
  "fmt"
)

func main() {

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

    // We need to provide a variable where Hjson
    // can put the decoded data.
    var dat map[string]interface{}

    // Decode and a check for errors.
    if err := hjson.Unmarshal(sampleText, &dat); err != nil {
        panic(err)
    }
    fmt.Println(dat)

    // In order to use the values in the decoded map,
    // we'll need to cast them to their appropriate type.

    rate := dat["rate"].(float64)
    fmt.Println(rate)

    array := dat["array"].([]interface{})
    str1 := array[0].(string)
    fmt.Println(str1)


    // To encode to Hjson with default options:
    sampleMap := map[string]int{"apple": 5, "lettuce": 7}
    hjson, _ := hjson.Marshal(sampleMap)
    // this is short for:
    // options := hjson.DefaultOptions()
    // hjson, _ := hjson.MarshalWithOptions(sampleMap, options)
    fmt.Println(string(hjson))
}

If you prefer, you can also unmarshal to Go objects by converting to JSON:

package main

import (
  "github.com/hjson/hjson-go"
  "encoding/json"
  "fmt"
)

type Sample struct {
    Rate  int
    Array []string
}

func main() {

    sampleText := []byte(`
    {
        # specify rate in requests/second
        rate: 1000
        array:
        [
            foo
            bar
        ]
    }`)

    // read Hjson
    var dat map[string]interface{}
    hjson.Unmarshal(sampleText, &dat)

    // convert to JSON
    b, _ := json.Marshal(dat)

    // unmarshal
    var sample Sample
    json.Unmarshal(b, &sample)

    fmt.Println(sample.Rate)
    fmt.Println(sample.Array)
}

API

godoc

History

see releases

Owner
Comments
  • need an option to preserve source file key order

    need an option to preserve source file key order

    i'm trying to remain compatible with a python implementation of the hjson format, and need the keys to remain in order.

    this is preventing me from being able to utilize this tool due to it's key sorting in the output.

    i understand that in go, a map is not guaranteed an order, but the keys could be imported into a list on read and exported back out in the same order that they appear, i.e. to simulate a python 'ordered dictionary.

    this doesn't need to be the default behaviour since often the sorting is desired, but as a compatibility option or flag to 'preserve key order' would be ideal.

    thank you for considering.

  • Add support for comments in structs

    Add support for comments in structs

    Allows comments to be added to struct definitions and included in the marshalled output. Comments containing \n will be split across multiple commented lines.

    As an example:

    type foo struct {
      a    string    `comment:"First comment"`
      b    int32     `comment:"Second comment\nLook ma, new lines"`
    }
    
    func main() {
    	a := foo{ a: "hi!", b: 3 }
    	h, err := hjson.Marshal(a)
    	if err != nil {
    		panic(err)
    	}
    	fmt.Println(string(h))
    }
    

    ... produces the following:

    {
      # First comment
      a: hi!
    
      # Second comment
      # Look ma, new lines
      b: 3
    }
    
  • adding .github/workflows/build.yml

    adding .github/workflows/build.yml

    to build binary releases based on pushed tags (git push --tags , git push --follow-tags an so on)....

    this workflow is designed to__NOT__ work if someone creates tags on the GitHub Website or pushes anything which is not a tag ;) ... but this can easily be changed, if desired :)

  • EOL defaults for Windows

    EOL defaults for Windows

    This defaults the EOL to \r\n on Windows. On other platforms the current default of \n is preserved.

    I understand that this behaviour can be overridden already using MarshalWithOptions, but it feels like we should endeavour to do what is natural for a given platform by default without doing anything special, particularly since Notepad and friends on Windows have a hard time with \n.

  • marshal an object with not export self pointer reference will run forever

    marshal an object with not export self pointer reference will run forever

    package main
    
    import (
    	"github.com/hjson/hjson-go"
    	"fmt"
    )
    
    func main(){
    	type Node struct{
    		self *Node
    	}
    	var obj Node
    	obj.self = &obj
    	b,err:=hjson.Marshal(obj)
    	if err!=nil{
    		panic(err)
    	}
    	fmt.Println(string(b))
    }
    

    It should ignore all not export field.

  • Easy way to unmarshal to struct without assertions?

    Easy way to unmarshal to struct without assertions?

    Hello,

    Sorry if the answer is too obvious as I'm a beginner in Go, but is there an easy way to do this with hjson and hjson-go without all the assertions as presented in the doc?

    Thanks

  • Preserve comments on source file

    Preserve comments on source file

    I was wondering if there is a way to Unmarshal hjson to a go struct but preserve arbitrary comments on the source json. For example if my hjson looks like this:

    {
    // random comment
      "foo": "bar",
      "foo2": "bar2"
    }
    

    I want to preserve a comment on a random line in the json, unmarshal the file to a go struct, change bar to bar-modified. Then marshal and save to file.

    Is it possible to preserve comments when you don't know which line might have a comment on it?

  • module path must match major version

    module path must match major version

    When fetching this package, I get the following error:

    go get github.com/hjson/[email protected]
    go: github.com/hjson/[email protected]: invalid version: module contains a go.mod file, so module path must match major version ("github.com/hjson/hjson-go/v3")
    

    It looks like that, according to https://github.com/golang/go/issues/35732, this can be fixed by modifying the path here: https://github.com/hjson/hjson-go/blob/e669f6bde0de3f1f87961258f47f7a78bd16bb60/go.mod#L1 ...to github.com/hjson/hjson-go/v3.

  • can not unmarshal obj from marshal result with string

    can not unmarshal obj from marshal result with string "0\r'"

    test code:

    func TestEncodeMarshalAndUnmarshal(t *testing.T) {
    	type t_obj struct{
    		F string
    	}
    	const testS = "0\r'"
    	input := t_obj{
    		F: "0\r'",
    	}
    	buf, err := Marshal(input)
    	if err != nil {
    		t.Fatal(err)
    	}
    	var obj2 t_obj
    	err = Unmarshal(buf,&obj2)
    	if err != nil {
    		t.Fatal(err)
    	}
    	if obj2.F!=testS{
    		t.Error("fail ["+hex.Dump([]byte(obj2.F))+`]`)
    	}
    }
    
  • support marshal net.ParseIP(`127.0.0.1`) to 127.0.0.1

    support marshal net.ParseIP(`127.0.0.1`) to 127.0.0.1

    support marshal net.ParseIP(127.0.0.1) to 127.0.0.1

    current result:

    [
      0
      0
      0
      0
      0
      0
      0
      0
      0
      0
      255
      255
      127
      0
      0
      1
    ]
    

    support encoding.TextMarshaler should fix this bug.

  • Fix Unmarshal panicking when called with a nil value

    Fix Unmarshal panicking when called with a nil value

    As per #16, Unmarshal panics when called with v=nil, so this PR aims to fix that. The new behavior can be seen at https://play.golang.org/p/uQDTVmAGRk_B, if there's anything missing just let me know

  • add UnmarshalPartially

    add UnmarshalPartially

    In our project, we use hjson as part of configs, it's mixed with other format texts. So we need read the part of hjson by hjson-go and keep the left part to other programs. I added the function UnmarshalPartially to do this work. UnmarshalPartially reads characters from the beginning, add try to parse them as hjson. It stops when meeting wrong formats or finishing a complete hjson structure. It returns the parsed value, the start position of the unprocessed part and error if has.

Related tags