json2go

package module
v1.1.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2021 License: MIT Imports: 12 Imported by: 0

README

json2go Build Go Report Card GoDoc Coverage Mentioned in Awesome Go

Package json2go provides utilities for creating go type representation from json inputs.

Json2go can be used in various ways:

Why another conversion tool?

There are few tools for converting json to go types available already. But all of which I tried worked correctly with only basic documents.

The goal of this project is to create types, that are guaranteed to properly unmarshal input data. There are multiple test cases that check marshaling/unmarshaling both ways to ensure generated type is accurate.

Here's the micro acid test if you want to check this or other conversion tools:

[{"date":"2020-10-03T15:04:05Z","text":"txt1","doc":{"x":"x"}},{"date":"2020-10-03T15:05:02Z","_doc":false,"arr":[[1,null,1.23]]},{"bool":true,"doc":{"y":123}}]

And correct output with some comments:

type Document []struct {
        Arr  [][]*float64 `json:"arr,omitempty"` // Should be doubly nested array; should be a pointer type because there's null in values.
        Bool *bool        `json:"bool,omitempty"` // Shouldn't be `bool` because when key is missing you'll get false information.
        Date *time.Time   `json:"date,omitempty"` // Could be also `string` or `*string`.
        Doc  *struct {
                X *string `json:"x,omitempty"` // Should be pointer, because key is not present in all documents.
                Y *int    `json:"y,omitempty"` // Should be pointer, because key is not present in all documents.
        } `json:"doc,omitempty"` // Should be pointer, because key is not present in all documents in array.
        Doc2 *bool   `json:"_doc,omitempty"` // Attribute for "_doc" key (other that for "doc"!). Type - the same as `Bool` attribute.
        Text *string `json:"text,omitempty"` // Could be also `string`.
}

CLI Installation

go get github.com/m-zajac/json2go/...

Usage

Json2go can be used as cli tool or as package.

CLI tools can be used directly to create go type from stdin data (see examples).

Package provides Parser, which can consume multiple jsons and outputs go type fitting all inputs (see examples and documentation). Example usage: read documents from document-oriented database and feed them too parser for go struct.

CLI usage examples
echo '{"x":1,"y":2}' | json2go

curl -s https://api.punkapi.com/v2/beers?page=1&per_page=5 | json2go

Check this one :)


cat data.json | json2go
Package usage examples
inputs := []string{
	`{"x": 123, "y": "test", "z": false}`,
	`{"a": 123, "x": 12.3, "y": true}`,
}

parser := json2go.NewJSONParser("Document")
for _, in := range inputs {
	parser.FeedBytes([]byte(in))
}

res := parser.String()
fmt.Println(res)

Example outputs

{
    "line": {
        "point1": {
            "x": 12.1,
            "y": 2
        },
        "point2": {
            "x": 12.1,
            "y": 2
        }
    }
}
type Document struct {
        Line struct {
                Point1 Point `json:"point1"`
                Point2 Point `json:"point2"`
        } `json:"line"`
}
type Point struct {
        X float64 `json:"x"`
        Y int     `json:"y"`
}

[
    {
        "name": "water",
        "type": "liquid",
        "boiling_point": {
            "units": "C",
            "value": 100
        }
    },
    {
        "name": "oxygen",
        "type": "gas",
        "density": {
            "units": "g/L",
            "value": 1.429
        }
    },
    {
        "name": "carbon monoxide",
        "type": "gas",
        "dangerous": true,
        "boiling_point": {
            "units": "C",
            "value": -191.5
        },
        "density": {
            "units": "kg/m3",
            "value": 789
        }
    }
]
type Document []struct {
        BoilingPoint *UnitsValue `json:"boiling_point,omitempty"`
        Dangerous    *bool       `json:"dangerous,omitempty"`
        Density      *UnitsValue `json:"density,omitempty"`
        Name         string      `json:"name"`
        Type         string      `json:"type"`
}
type UnitsValue struct {
        Units string  `json:"units"`
        Value float64 `json:"value"`
}

Contribution

I'd love your input! Especially reporting bugs and proposing new features.

Documentation

Overview

Package json2go implements decoding json strings to go type representation.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type JSONParser

type JSONParser struct {
	// contains filtered or unexported fields
}

JSONParser parses successive json inputs and returns go representation as string

func NewJSONParser

func NewJSONParser(rootTypeName string, opts ...JSONParserOpt) *JSONParser

NewJSONParser creates new json Parser

Example
inputs := []string{
	`{"line":{"start":{"x":12.1,"y":2.8},"end":{"x":12.1,"y":5.67}}}`,
	`{"triangle":[{"x":2.34,"y":2.1}, {"x":45.1,"y":6.7}, {"x":4,"y":94.6}]}`,
}

parser := NewJSONParser(
	"Document",
	OptExtractCommonTypes(true),
)

for _, in := range inputs {
	_ = parser.FeedBytes([]byte(in))
}

res := parser.String()
fmt.Println(res)
Output:

type Document struct {
	Line *struct {
		End   XY `json:"end"`
		Start XY `json:"start"`
	} `json:"line,omitempty"`
	Triangle []XY `json:"triangle,omitempty"`
}
type XY struct {
	X float64 `json:"x"`
	Y float64 `json:"y"`
}

func (*JSONParser) ASTDecls

func (p *JSONParser) ASTDecls() []ast.Decl

ASTDecls returns ast type declarations

func (*JSONParser) FeedBytes

func (p *JSONParser) FeedBytes(input []byte) error

FeedBytes consumes json input as bytes. If input is invalid, json unmarshalling error is returned

func (*JSONParser) FeedValue

func (p *JSONParser) FeedValue(input interface{})

FeedValue consumes one of:

  • simple type (int, float, string, etc.)
  • []interface{} - each value must meet these requirements
  • map[string]interface{} - each value must meet these requirements

json.Unmarshal to empty interface value provides perfect input (see example)

Example
var v interface{}
_ = json.Unmarshal([]byte(`{"line":{"start":{"x":12.1,"y":2.8},"end":{"x":12.1,"y":5.67}}}`), &v)

parser := NewJSONParser("Document")
parser.FeedValue(v)
res := parser.String()
fmt.Println(res)
Output:

type Document struct {
	Line struct {
		End struct {
			X float64 `json:"x"`
			Y float64 `json:"y"`
		} `json:"end"`
		Start struct {
			X float64 `json:"x"`
			Y float64 `json:"y"`
		} `json:"start"`
	} `json:"line"`
}

func (*JSONParser) String

func (p *JSONParser) String() string

String returns string representation of go struct fitting parsed json values

type JSONParserOpt

type JSONParserOpt func(*options)

JSONParserOpt is a type for setting parser options.

func OptExtractCommonTypes

func OptExtractCommonTypes(v bool) JSONParserOpt

OptExtractCommonTypes toggles extracting common json nodes as separate types.

func OptMakeMaps

func OptMakeMaps(v bool, minAttributes uint) JSONParserOpt

OptMakeMaps defines if parser should try to use maps instead of structs when possible. minAttributes defines minimum number of attributes in object to try converting it to a map.

func OptSkipEmptyKeys

func OptSkipEmptyKeys(v bool) JSONParserOpt

OptSkipEmptyKeys toggles skipping keys in input that were only nulls.

func OptStringPointersWhenKeyMissing

func OptStringPointersWhenKeyMissing(v bool) JSONParserOpt

OptStringPointersWhenKeyMissing toggles wether missing string key in one of documents should result in pointer string.

func OptTimeAsString

func OptTimeAsString(v bool) JSONParserOpt

OptTimeAsString toggles using time.Time for valid time strings or just a string.

Directories

Path Synopsis
cmd
deployments

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL