Skip to content

Commit

Permalink
Update README and doc
Browse files Browse the repository at this point in the history
  • Loading branch information
iOliverNguyen committed Mar 3, 2019
1 parent 5c82df0 commit 565e133
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 12 deletions.
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
[![Build Status](https://travis-ci.org/ng-vu/ujson.svg?branch=master)](https://travis-ci.org/ng-vu/ujson)
[![GoDoc](https://img.shields.io/badge/godoc-reference-blue.svg)](http://godoc.org/github.com/ng-vu/ujson)

A minimal implementation of a json parser and transformer. Example use cases:
A fast and minimal JSON parser and transformer that works on unstructured json.
Example use cases:

1. Walk through unstructured json:
- [Print all keys and values](https://godoc.org/github.com/ng-vu/ujson#example-Walk)
Expand All @@ -20,6 +21,62 @@ See usage and examples on [godoc.org](https://godoc.org/github.com/ng-vu/ujson).

**CAUTION: Behaviour is undefined on invalid json. Use on trusted input only.**

## Usage

The single most important function is [`Walk(input, callback)`](https://godoc.org/github.com/ng-vu/ujson#Walk),
which parses the `input` json and call `callback` function for each key/value
pair processed.

Let's see an example:

```json
{
"id": 12345,
"name": "foo",
"numbers": ["one", "two"],
"tags": {"color": "red", "priority": "high"},
"active": true
}
```

Calling `Walk()` with the above input will produce:

| indent | key | value |
|:------:|:----------:|:-------:|
|`0` | |`{` |
|`1` |`"id"` |`12345` |
|`1` |`"name"` |`"foo"` |
|`1` |`"numbers"` |`[` |
|`2` | |`"one"` |
|`2` | |`"two"` |
|`1` | |`]` |
|`1` |`"tags"` |`{` |
|`2` |`"color"` |`"red"` |
|`2` |`"priority"`|`"high"` |
|`1` | |`}` |
|`1` |`"active"` |`true` |
|`0` | |`}` |

`indent` indicates the indentation of the key/value pair as if the json is
formatted properly. `key`s and `value`s are provided as raw literal. Strings are
always double-quoted. To get the original string, use
[`Unquote()`](https://godoc.org/github.com/ng-vu/ujson#Unquote).

`value` will never be empty (for valid json). You can test the first byte
(`value[0]`) to get its type:

- `n`: Null (`null`)
- `f`, `t`: Boolean (`false`, `true`)
- `0`-`9`: Number
- `"`: String, see [`Unquote()`](https://godoc.org/github.com/ng-vu/ujson#Unquote)
- `[`, `]`: Array
- `{`, `}`: Object

When processing arrays and objects, first the open bracket (`[`, `{`) will be
provided as `value`, followed by its children, and finally the close bracket
(`]`, `}`). When encounting open brackets, You can make the callback function
return `false` to skip the array/object entirely.

## LICENSE

[MIT License](https://opensource.org/licenses/mit-license.php)
10 changes: 5 additions & 5 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import (
func ExampleWalk() {
input := []byte(`{"order_id": 12345678901234, "number": 12, "item_id": 12345678905678, "counting": [1,"2",3]}`)

err := ujson.Walk(input, func(st int, key, value []byte) bool {
fmt.Println(st, string(key), string(value))
err := ujson.Walk(input, func(indent int, key, value []byte) bool {
fmt.Println(indent, string(key), string(value))
return true
})
if err != nil {
Expand All @@ -34,7 +34,7 @@ func ExampleWalk_reconstruct() {
input := []byte(`{"order_id": 12345678901234, "number": 12, "item_id": 12345678905678, "counting": [1,"2",3]}`)

b := make([]byte, 0, 256)
err := ujson.Walk(input, func(st int, key, value []byte) bool {
err := ujson.Walk(input, func(indent int, key, value []byte) bool {
if len(b) != 0 && ujson.ShouldAddComma(value, b[len(b)-1]) {
b = append(b, ',')
}
Expand All @@ -56,12 +56,12 @@ func ExampleWalk_reformat() {
input := []byte(`{"order_id": 12345678901234, "number": 12, "item_id": 12345678905678, "counting": [1,"2",3]}`)

b := make([]byte, 0, 256)
err := ujson.Walk(input, func(st int, key, value []byte) bool {
err := ujson.Walk(input, func(indent int, key, value []byte) bool {
if len(b) != 0 && ujson.ShouldAddComma(value, b[len(b)-1]) {
b = append(b, ',')
}
b = append(b, '\n')
for i := 0; i < st; i++ {
for i := 0; i < indent; i++ {
b = append(b, '\t')
}
if len(key) > 0 {
Expand Down
2 changes: 1 addition & 1 deletion quote.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func AppendQuoteString(dst []byte, s string) []byte {
}

// Unquote decodes a double-quoted string key or value to retrieve the
// underlying string value. It will avoid allocation whenever possible.
// original string value. It will avoid allocation whenever possible.
//
// The code is inspired by strconv.Unquote, but only accepts valid json string.
func Unquote(s []byte) ([]byte, error) {
Expand Down
58 changes: 53 additions & 5 deletions µjson.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Package µjson implements a minimal JSON parser and transformer (works with
// valid input only). Example use cases:
// Package µjson implements a fast and minimal JSON parser and transformer that
// works on unstructured json. Example use cases:
//
// 1. Walk through unstructured json:
// - Print all keys and values
Expand All @@ -13,19 +13,67 @@
// without fully unmarshalling it into a map[string]interface{}
//
// CAUTION: Behaviour is undefined on invalid json. Use on trusted input only.
//
// The single most important function is "Walk()", which parses the given json
// and call callback function for each key/value pair processed.
//
// {
// "id": 12345,
// "name": "foo",
// "numbers": ["one", "two"],
// "tags": {"color": "red", "priority": "high"},
// "active": true
// }
//
// Calling "Walk()" with the above input will produce:
//
// | indent | key | value |
// |--------|------------|---------|
// | 0 | | { |
// | 1 | "id" | 12345 |
// | 1 | "name" | "foo" |
// | 1 | "numbers" | [ |
// | 2 | | "one" |
// | 2 | | "two" |
// | 1 | | ] |
// | 1 | "tags" | { |
// | 2 | "color" | "red" |
// | 2 | "priority" | "high" |
// | 1 | | } |
// | 1 | "active" | true |
// | 0 | | } |
//
// "indent" indicates the indentation of the key/value pair as if the json is
// formatted properly. Keys and values are provided as raw literal. Strings are
// always double-quoted. To get the original string, use "Unquote".
//
// "value" will never be empty (for valid json). You can test the first byte
// ("value[0]") to get its type:
//
// - 'n' : Null ("null")
// - 'f', 't': Boolean ("false", "true")
// - '0'-'9' : Number
// - '"' : String, see "Unquote"
// - '[', ']': Array
// - '{', '}': Object
//
// When processing arrays and objects, first the open bracket ("[", "{") will be
// provided as "value", followed by its children, and finally the close bracket
// ("]", "}"). When encounting open brackets, You can make the callback function
// return "false" to skip the array/object entirely.
package ujson

import "fmt"

// Walk parses the given json and call "callback" for each key. See examples for
// sample callback params.
// Walk parses the given json and call "callback" for each key/value pair. See
// examples for sample callback params.
//
// The function "callback":
//
// - may convert key and value to string for processing
// - may return false to skip processing the current object or array
// - must not modify any slice it receives.
func Walk(input []byte, callback func(st int, key, value []byte) bool) error {
func Walk(input []byte, callback func(indent int, key, value []byte) bool) error {
var key []byte
i, si, ei, st, sst := 0, 0, 0, 0, 1024

Expand Down

0 comments on commit 565e133

Please sign in to comment.