Showing preview only (1,433K chars total). Download the full file or copy to clipboard to get everything.
Repository: tomnomnom/gron
Branch: master
Commit: 88a6234ea2d0
Files: 62
Total size: 1.4 MB
Directory structure:
gitextract_i63kwxl_/
├── .github/
│ └── workflows/
│ ├── build.yml
│ └── release.yml
├── .gitignore
├── .goreleaser.yml
├── .travis.yml
├── ADVANCED.mkd
├── CHANGELOG.mkd
├── CONTRIBUTING.mkd
├── LICENSE
├── README.mkd
├── completions/
│ ├── gron.bash
│ └── gron.fish
├── docs/
│ └── index.html
├── go.mod
├── go.sum
├── identifier.go
├── identifier_test.go
├── main.go
├── main_test.go
├── original-gron.php
├── script/
│ ├── example
│ ├── lint
│ ├── precommit
│ ├── profile
│ ├── release
│ └── test
├── statements.go
├── statements_test.go
├── testdata/
│ ├── big.json
│ ├── github.gron
│ ├── github.jgron
│ ├── github.json
│ ├── grep-separators.gron
│ ├── grep-separators.json
│ ├── invalid-type-mismatch.gron
│ ├── invalid-value.gron
│ ├── large-line.gron
│ ├── large-line.json
│ ├── long-stream.gron
│ ├── long-stream.json
│ ├── one.gron
│ ├── one.jgron
│ ├── one.json
│ ├── scalar-stream.gron
│ ├── scalar-stream.jgron
│ ├── scalar-stream.json
│ ├── stream.gron
│ ├── stream.jgron
│ ├── stream.json
│ ├── three.gron
│ ├── three.jgron
│ ├── three.json
│ ├── two-b.json
│ ├── two.gron
│ ├── two.jgron
│ └── two.json
├── token.go
├── token_test.go
├── ungron.go
├── ungron_test.go
├── url.go
└── url_test.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/build.yml
================================================
name: Go
on:
push:
branches:
- master
pull_request:
workflow_dispatch:
jobs:
build:
strategy:
matrix:
go-version: ['stable', 'oldstable']
os: [ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v4
- name: Install Go
if: success()
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache: true
- name: Run tests
run: go test
================================================
FILE: .github/workflows/release.yml
================================================
name: release
on:
push:
tags:
- "*"
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 'stable'
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }}
================================================
FILE: .gitignore
================================================
gron
*.tgz
*.zip
*.swp
*.exe
cpu.out
gron.test
vendor
================================================
FILE: .goreleaser.yml
================================================
version: 2
before:
hooks:
- go mod tidy
- go mod vendor
source:
enabled: true
files:
- vendor
================================================
FILE: .travis.yml
================================================
language: go
go:
- "1.13"
- "1.14"
- "1.15"
- "1.16"
- "1.17"
- "1.18"
- "1.19"
- "1.20"
- "1.21"
- "1.22"
- "1.23"
- tip
================================================
FILE: ADVANCED.mkd
================================================
# Advanced Usage
Although gron's primary purpose is API discovery, when combined with other tools like `grep` it can do some interesting things.
As an exercise, let's try to mimick some of the examples from the [jq tutorial](https://stedolan.github.io/jq/tutorial/).
> Disclaimer: munging data on the command line with gron can be useful, but using tools like `grep` and `sed` to manipulate the
> data is error-prone and shouldn't be relied on in scripts.
Get the last 5 commits from the gron repo:
```
▶ gron "https://api.github.com/repos/tomnomnom/gron/commits?per_page=5"
json = [];
json[0] = {};
json[0].author = {};
json[0].author.avatar_url = "https://avatars.githubusercontent.com/u/58276?v=3";
json[0].author.events_url = "https://api.github.com/users/tomnomnom/events{/privacy}";
...
json[4].parents[0].html_url = "https://github.com/tomnomnom/gron/commit/cbcad2299e55c28a9922776e58b2a0b5a0f05016";
json[4].parents[0].sha = "cbcad2299e55c28a9922776e58b2a0b5a0f05016";
json[4].parents[0].url = "https://api.github.com/repos/tomnomnom/gron/commits/cbcad2299e55c28a9922776e58b2a0b5a0f05016";
json[4].sha = "91b204972e63a1166c9d148fbbfd839f8697f91b";
json[4].url = "https://api.github.com/repos/tomnomnom/gron/commits/91b204972e63a1166c9d148fbbfd839f8697f91b";
```
To make the rest of this a little more readable, let's add an alias for that:
```
▶ alias ggh='gron "https://api.github.com/repos/tomnomnom/gron/commits?per_page=5"'
```
Extract just the first commit using `fgrep "json[0]"`:
```
▶ ggh | fgrep "json[0]"
json[0] = {};
json[0].author = {};
json[0].author.avatar_url = "https://avatars.githubusercontent.com/u/58276?v=3";
json[0].author.events_url = "https://api.github.com/users/tomnomnom/events{/privacy}";
json[0].author.followers_url = "https://api.github.com/users/tomnomnom/followers";
...
json[0].parents[0].html_url = "https://github.com/tomnomnom/gron/commit/48aba5325ece087ae24ab72684851cbe77ce8311";
json[0].parents[0].sha = "48aba5325ece087ae24ab72684851cbe77ce8311";
json[0].parents[0].url = "https://api.github.com/repos/tomnomnom/gron/commits/48aba5325ece087ae24ab72684851cbe77ce8311";
json[0].sha = "7da81e29c27241c0a5c2e5d083ddebcfcc525908";
json[0].url = "https://api.github.com/repos/tomnomnom/gron/commits/7da81e29c27241c0a5c2e5d083ddebcfcc525908";
```
Get just the committer's name and the commit message using `egrep "(committer.name|commit.message)"`:
```
▶ ggh | fgrep "json[0]" | egrep "(committer.name|commit.message)"
json[0].commit.committer.name = "Tom Hudson";
json[0].commit.message = "Adds 0.1.7 to changelog";
```
Turn the result back into JSON using `gron --ungron`:
```
▶ ggh | fgrep "json[0]" | egrep "(committer.name|commit.message)" | gron --ungron
[
{
"commit": {
"committer": {
"name": "Tom Hudson"
},
"message": "Adds 0.1.7 to changelog"
}
}
]
```
gron preserves the location of values in the JSON, but you can use `sed` to remove keys from the path:
```
▶ ggh | fgrep "json[0]" | egrep "(committer.name|commit.message)" | sed -r "s/(commit|committer)\.//g"
json[0].name = "Tom Hudson";
json[0].message = "Adds 0.1.7 to changelog"
```
With those keys removed, the result is a 'flattened' object, which looks much cleaner when turned
back into JSON with `gron --ungron`:
```
▶ ggh | fgrep "json[0]" | egrep "(committer.name|commit.message)" | sed -r "s/(commit|committer)\.//g" | gron --ungron
[
{
"message": "Adds 0.1.7 to changelog",
"name": "Tom Hudson"
}
]
```
Removing the `fgrep "json[0]"` from the pipeline means we do the same for all commits:
```
▶ ggh | egrep "(committer.name|commit.message)" | sed -r "s/(commit|committer)\.//g" | gron --ungron
[
{
"message": "Adds 0.1.7 to changelog",
"name": "Tom Hudson"
},
{
"message": "Refactors natural sort to actually work + be more readable",
"name": "Tom Hudson"
},
...
```
To include the `html_url` key for each commit's parents, all we need to do is add `parents.*html_url` into our call to `egrep`:
```
▶ ggh | egrep "(committer.name|commit.message|parents.*html_url)" | sed -r "s/(commit|committer)\.//g"
json[0].name = "Tom Hudson";
json[0].message = "Adds 0.1.7 to changelog";
json[0].parents[0].html_url = "https://github.com/tomnomnom/gron/commit/48aba5325ece087ae24ab72684851cbe77ce8311";
json[1].name = "Tom Hudson";
json[1].message = "Refactors natural sort to actually work + be more readable";
json[1].parents[0].html_url = "https://github.com/tomnomnom/gron/commit/3eca8bf5e07151f077cebf0d942c1fa8bc51e8f2";
...
```
To make the structure more like that in the final example in the `jq` tutorial, we can use `sed -r "s/\.html_url//"` to remove the `.html_url` part of the path:
```
▶ ggh | egrep "(committer.name|commit.message|parents.*html_url)" | sed -r "s/(commit|committer)\.//g" | sed -r "s/\.html_url//"
json[0].name = "Tom Hudson";
json[0].message = "Adds 0.1.7 to changelog";
json[0].parents[0] = "https://github.com/tomnomnom/gron/commit/48aba5325ece087ae24ab72684851cbe77ce8311";
json[1].name = "Tom Hudson";
json[1].message = "Refactors natural sort to actually work + be more readable";
json[1].parents[0] = "https://github.com/tomnomnom/gron/commit/3eca8bf5e07151f077cebf0d942c1fa8bc51e8f2";
...
```
And, of course, the statements can be turned back into JSON with `gron --ungron`:
```
▶ ggh | egrep "(committer.name|commit.message|parents.*html_url)" | sed -r "s/(commit|committer)\.//g" | sed -r "s/\.html_url//" | gron --ungron
[
{
"message": "Adds 0.1.7 to changelog",
"name": "Tom Hudson",
"parents": [
"https://github.com/tomnomnom/gron/commit/48aba5325ece087ae24ab72684851cbe77ce8311"
]
},
{
"message": "Refactors natural sort to actually work + be more readable",
"name": "Tom Hudson",
"parents": [
"https://github.com/tomnomnom/gron/commit/3eca8bf5e07151f077cebf0d942c1fa8bc51e8f2"
]
},
...
```
================================================
FILE: CHANGELOG.mkd
================================================
# Changelog
## 0.6.0
- Adds `--json`/JSON stream output support (thanks @csabahenk!)
- Removes trailing newline character for monochrome output (issue #43)
## 0.5.2
- Built with Go 1.10 to fix issue #32 - Thanks @VladimirAlexiev and @joekyo!
## 0.5.1
- Fixes bug where empty identifiers would be treated as bare words (thanks for the report, @waltertross!)
## 0.5.0
- Adds `-k`/`--insecure` to disable validation of certificates when fetching URLs (thanks @jagsta!)
## 0.4.0
- Adds `-c`/`--colorize` to force colorization of output (thanks @orivej!)
- Adds `-s`/`--stream` option to read one JSON object per line
- Native string quoting (performance improvement)
- Fixes bug with strings ending in a double-slash (issue #25)
## 0.3.7
- HTML characters (`<`, `>` etc) are no-longer escaped in gron output (issue #22)
## 0.3.6
- Fixes bug where invalid statements were outputted
## 0.3.5
- General performance improvements; 5 to 17 times faster (see issue #21 for details)
## 0.3.4
- Speed improvements when using `--monochrome`
- Adds `--no-sort` option
## 0.3.3
- Slightly improved error reporting when ungronning
- 20 second timeout on HTTP(s) requests (thanks @gummiboll!)
- Version information added at build time + `--version` option (issue #19)
## 0.3.2
- Adds handling of `--` lines produced by grep -A etc (issue #15)
## 0.3.1
- Built with Go 1.7!
- Up to 25% faster
- 40% smaller binaries
## 0.3.0
- Adds colorized gron output
- Fixes formatting of large ints in ungron output (issue #12)
## 0.2.9
- Adds colorized ungron output (thanks @nwidger!)
- Adds 32 bit binaries to releases
## 0.2.8
- Adds freebsd release binaries
## 0.2.7
- Fixes bad handling of escape sequences when ungronning - but properly this time (issue #7)
## 0.2.5
- Fixes bad handling of escape sequences when ungronning (issue #7)
## 0.2.4
- Fixes handling of large integers (issue #6)
## 0.2.3
- Switches Windows binary packaging to zip instead of tgz
## 0.2.2
- Tweaks release automation, no user-facing changes
## 0.2.1
- Adds windows binary
## 0.2.0
- Adds [ungronning](README.mkd#ungronning)!
## 0.1.7
- Fixes sorting of array keys; now uses natural sort
## 0.1.6
- Adds proper handling of key quoting using Unicode ranges
- Adds basic benchmarks
- Adds profiling script
## 0.1.5
- Adds scripted builds for darwin on amd64
## 0.1.4
- Minor changes to release script
## 0.1.3
- Releases are now tarballs
## 0.1.2
- Underscores no-longer cause keys to be quoted
- HTTP requests are now done with `Accept: application/json`
- HTTP requests are now done with `User-Agent: gron/0.1`
## 0.1.1
- Adds support for fetching URLs directly
## 0.1.0
- Support for files
- Support for `stdin`
================================================
FILE: CONTRIBUTING.mkd
================================================
# Contributing
* Raise an issue if appropriate
* Fork the repo
* Make your changes
* Use [gofmt](https://golang.org/cmd/gofmt/)
* Make sure the tests pass (run `./script/test`)
* Make sure the linters pass (run `./script/lint`)
* Issue a pull request
## Commit Messages
I'd prefer it if commit messages describe what the *commit does*, not what *you did*.
For example, I'd prefer:
```
Adds lint; removes fluff
```
Over:
```
Added lint; removed fluff
```
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2016 Tom Hudson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.mkd
================================================
# gron
[](https://travis-ci.org/tomnomnom/gron)
Make JSON greppable!
gron transforms JSON into discrete assignments to make it easier to `grep` for what you want and see the absolute 'path' to it.
It eases the exploration of APIs that return large blobs of JSON but have terrible documentation.
<pre>
▶ <b>gron</b> "https://api.github.com/repos/tomnomnom/gron/commits?per_page=1" | fgrep "commit.author"
json[0].commit.author = {};
json[0].commit.author.date = "2016-07-02T10:51:21Z";
json[0].commit.author.email = "mail@tomnomnom.com";
json[0].commit.author.name = "Tom Hudson";
</pre>
gron can work backwards too, enabling you to turn your filtered data back into JSON:
<pre>
▶ gron "https://api.github.com/repos/tomnomnom/gron/commits?per_page=1" | fgrep "commit.author" | <b>gron --ungron</b>
[
{
"commit": {
"author": {
"date": "2016-07-02T10:51:21Z",
"email": "mail@tomnomnom.com",
"name": "Tom Hudson"
}
}
}
]
</pre>
> Disclaimer: the GitHub API has fantastic documentation, but it makes for a good example.
## Installation
gron has no runtime dependencies. You can just [download a binary for Linux, Mac, Windows or FreeBSD and run it](https://github.com/tomnomnom/gron/releases).
Put the binary in your `$PATH` (e.g. in `/usr/local/bin`) to make it easy to use:
```
▶ tar xzf gron-linux-amd64-0.1.5.tgz
▶ sudo mv gron /usr/local/bin/
```
If you're a Mac user you can also [install gron via brew](http://braumeister.org/formula/gron):
```
▶ brew install gron
```
Or if you're a Go user you can use `go install`:
```
▶ go install github.com/tomnomnom/gron@latest
```
It's recommended that you alias `ungron` or `norg` (or both!) to `gron --ungron`. Put something like this in your shell profile (e.g. in `~/.bashrc`):
```
alias norg="gron --ungron"
alias ungron="gron --ungron"
```
Or you could create a shell script in your $PATH named `ungron` or `norg` to affect all users:
```
gron --ungron "$@"
```
## Usage
Get JSON from a file:
```
▶ gron testdata/two.json
json = {};
json.contact = {};
json.contact.email = "mail@tomnomnom.com";
json.contact.twitter = "@TomNomNom";
json.github = "https://github.com/tomnomnom/";
json.likes = [];
json.likes[0] = "code";
json.likes[1] = "cheese";
json.likes[2] = "meat";
json.name = "Tom";
```
From a URL:
```
▶ gron http://headers.jsontest.com/
json = {};
json.Host = "headers.jsontest.com";
json["User-Agent"] = "gron/0.1";
json["X-Cloud-Trace-Context"] = "6917a823919477919dbc1523584ba25d/11970839830843610056";
```
Or from `stdin`:
```
▶ curl -s http://headers.jsontest.com/ | gron
json = {};
json.Accept = "*/*";
json.Host = "headers.jsontest.com";
json["User-Agent"] = "curl/7.43.0";
json["X-Cloud-Trace-Context"] = "c70f7bf26661c67d0b9f2cde6f295319/13941186890243645147";
```
Grep for something and easily see the path to it:
```
▶ gron testdata/two.json | grep twitter
json.contact.twitter = "@TomNomNom";
```
gron makes diffing JSON easy too:
```
▶ diff <(gron two.json) <(gron two-b.json)
3c3
< json.contact.email = "mail@tomnomnom.com";
---
> json.contact.email = "contact@tomnomnom.com";
```
The output of `gron` is valid JavaScript:
```
▶ gron testdata/two.json > tmp.js
▶ echo "console.log(json);" >> tmp.js
▶ nodejs tmp.js
{ contact: { email: 'mail@tomnomnom.com', twitter: '@TomNomNom' },
github: 'https://github.com/tomnomnom/',
likes: [ 'code', 'cheese', 'meat' ],
name: 'Tom' }
```
It's also possible to obtain the `gron` output as JSON stream via
the `--json` switch:
```
▶ curl -s http://headers.jsontest.com/ | gron --json
[[],{}]
[["Accept"],"*/*"]
[["Host"],"headers.jsontest.com"]
[["User-Agent"],"curl/7.43.0"]
[["X-Cloud-Trace-Context"],"c70f7bf26661c67d0b9f2cde6f295319/13941186890243645147"]
```
## ungronning
gron can also turn its output back into JSON:
```
▶ gron testdata/two.json | gron -u
{
"contact": {
"email": "mail@tomnomnom.com",
"twitter": "@TomNomNom"
},
"github": "https://github.com/tomnomnom/",
"likes": [
"code",
"cheese",
"meat"
],
"name": "Tom"
}
```
This means you use can use gron with `grep` and other tools to modify JSON:
```
▶ gron testdata/two.json | grep likes | gron --ungron
{
"likes": [
"code",
"cheese",
"meat"
]
}
```
or
```
▶ gron --json testdata/two.json | grep likes | gron --json --ungron
{
"likes": [
"code",
"cheese",
"meat"
]
}
```
To preserve array keys, arrays are padded with `null` when values are missing:
```
▶ gron testdata/two.json | grep likes | grep -v cheese
json.likes = [];
json.likes[0] = "code";
json.likes[2] = "meat";
▶ gron testdata/two.json | grep likes | grep -v cheese | gron --ungron
{
"likes": [
"code",
null,
"meat"
]
}
```
If you get creative you can do [some pretty neat tricks with gron](ADVANCED.mkd), and
then ungron the output back into JSON.
## Get Help
```
▶ gron --help
Transform JSON (from a file, URL, or stdin) into discrete assignments to make it greppable
Usage:
gron [OPTIONS] [FILE|URL|-]
Options:
-u, --ungron Reverse the operation (turn assignments back into JSON)
-v, --values Print just the values of provided assignments
-c, --colorize Colorize output (default on tty)
-m, --monochrome Monochrome (don't colorize output)
-s, --stream Treat each line of input as a separate JSON object
-k, --insecure Disable certificate validation
-j, --json Represent gron data as JSON stream
--no-sort Don't sort output (faster)
--version Print version information
Exit Codes:
0 OK
1 Failed to open file
2 Failed to read input
3 Failed to form statements
4 Failed to fetch URL
5 Failed to parse statements
6 Failed to encode JSON
Examples:
gron /tmp/apiresponse.json
gron http://jsonplaceholder.typicode.com/users/1
curl -s http://jsonplaceholder.typicode.com/users/1 | gron
gron http://jsonplaceholder.typicode.com/users/1 | grep company | gron --ungron
```
## FAQ
### Wasn't this written in PHP before?
Yes it was! The original version is [preserved here for posterity](https://github.com/tomnomnom/gron/blob/master/original-gron.php).
### Why the change to Go?
Mostly to remove PHP as a dependency. There's a lot of people who work with JSON who don't have PHP installed.
### Why shouldn't I just use jq?
[jq](https://stedolan.github.io/jq/) is *awesome*, and a lot more powerful than gron, but with that power comes
complexity. gron aims to make it easier to use the tools you already know, like `grep` and `sed`.
gron's primary purpose is to make it easy to find the path to a value in a deeply nested JSON blob
when you don't already know the structure; much of jq's power is unlocked only once you know that structure.
================================================
FILE: completions/gron.bash
================================================
#!/usr/bin/env bash
# Bash shell commandline completions for gron.
#
# Copy the contents of this file into your ~/.bashrc file or whatever
# file you use for Bash completions.
#
# Example: cat ./completions/gron.bash >> ~/.bashrc
function _gron_completion {
local AVAILABLE_COMMANDS="--colorize --insecure --json --monochrome --no-sort --stream --ungron --values --version"
COMPREPLY=()
local CURRENT_WORD=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($(compgen -W "$AVAILABLE_COMMANDS" -- "$CURRENT_WORD"))
}
complete -F _gron_completion gron
================================================
FILE: completions/gron.fish
================================================
#!/usr/bin/env fish
# Fish shell commandline completions for gron.
#
# Stick this file in your ~/.config/fish/completions/ directory.
complete -c gron -s u -l ungron --description "Reverse the operation (turn assignments back into JSON)"
complete -c gron -s c -l colorize --description "Colorize output (default on tty)"
complete -c gron -s m -l monochrome --description "Monochrome (don't colorize output)"
complete -c gron -s s -l stream --description "Treat each line of input as a separate JSON object"
complete -c gron -s k -l insecure --description "Disable certificate validation"
complete -c gron -s j -l json --description "Represent gron data as JSON stream"
complete -c gron -l no-sort --description "Don't sort output (faster)"
complete -c gron -l version --description "Print version information"
# eof
================================================
FILE: docs/index.html
================================================
<!doctype html>
<html lang="en">
<head>
<title>gron</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<h1>gron</h1>
<h2>Ungron Input Grammar</h2>
<pre>
Input ::= '--'* Statement (Statement | '--')*
Statement ::= Path Space* "=" Space* Value ";" "\n"
Path ::= (BareWord) ("." BareWord | ("[" Key "]"))*
Value ::= String | Number | "true" | "false" | "null" | "[]" | "{}"
BareWord ::= (UnicodeLu | UnicodeLl | UnicodeLm | UnicodeLo | UnicodeNl | '$' | '_') (UnicodeLu | UnicodeLl | UnicodeLm | UnicodeLo | UnicodeNl | UnicodeMn | UnicodeMc | UnicodeNd | UnicodePc | '$' | '_')*
Key ::= [0-9]+ | String
String ::= '"' (UnescapedRune | ("\" (["\/bfnrt] | ('u' Hex))))* '"'
UnescapedRune ::= [^#x0-#x1f"\]
</pre>
<h3>Input</h3>
<img src="images/input.png">
<h3>Statement</h3>
<img src="images/statement.png">
<h3>Path</h3>
<img src="images/path.png">
<h3>Value</h3>
<img src="images/value.png">
<h3>BareWord</h3>
<img src="images/bareword.png">
<h3>Key</h3>
<img src="images/key.png">
<h3>String</h3>
<img src="images/string.png">
<h3>UnescapedRune</h3>
<img src="images/unescapedrune.png">
</body>
</html>
================================================
FILE: go.mod
================================================
module github.com/tomnomnom/gron
go 1.24
require (
github.com/fatih/color v1.18.0
github.com/mattn/go-colorable v0.1.14
github.com/nwidger/jsoncolor v0.3.2
github.com/pkg/errors v0.9.1
)
require (
github.com/mattn/go-isatty v0.0.20 // indirect
golang.org/x/sys v0.33.0 // indirect
)
================================================
FILE: go.sum
================================================
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/nwidger/jsoncolor v0.3.2 h1:rVJJlwAWDJShnbTYOQ5RM7yTA20INyKXlJ/fg4JMhHQ=
github.com/nwidger/jsoncolor v0.3.2/go.mod h1:Cs34umxLbJvgBMnVNVqhji9BhoT/N/KinHqZptQ7cf4=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
================================================
FILE: identifier.go
================================================
package main
import "unicode"
// The javascript reserved words cannot be used as unquoted keys
var reservedWords = map[string]bool{
"break": true,
"case": true,
"catch": true,
"class": true,
"const": true,
"continue": true,
"debugger": true,
"default": true,
"delete": true,
"do": true,
"else": true,
"export": true,
"extends": true,
"false": true,
"finally": true,
"for": true,
"function": true,
"if": true,
"import": true,
"in": true,
"instanceof": true,
"new": true,
"null": true,
"return": true,
"super": true,
"switch": true,
"this": true,
"throw": true,
"true": true,
"try": true,
"typeof": true,
"var": true,
"void": true,
"while": true,
"with": true,
"yield": true,
}
// validIdentifier checks to see if a string is a valid
// JavaScript identifier
// E.g:
//
// justLettersAndNumbers1 -> true
// a key with spaces -> false
// 1startsWithANumber -> false
func validIdentifier(s string) bool {
if reservedWords[s] || s == "" {
return false
}
for i, r := range s {
if i == 0 && !validFirstRune(r) {
return false
}
if i != 0 && !validSecondaryRune(r) {
return false
}
}
return true
}
// validFirstRune returns true for runes that are valid
// as the first rune in an identifier.
// E.g:
//
// 'r' -> true
// '7' -> false
func validFirstRune(r rune) bool {
return unicode.In(r,
unicode.Lu,
unicode.Ll,
unicode.Lm,
unicode.Lo,
unicode.Nl,
) || r == '$' || r == '_'
}
// validSecondaryRune returns true for runes that are valid
// as anything other than the first rune in an identifier.
func validSecondaryRune(r rune) bool {
return validFirstRune(r) ||
unicode.In(r, unicode.Mn, unicode.Mc, unicode.Nd, unicode.Pc)
}
================================================
FILE: identifier_test.go
================================================
package main
import "testing"
func TestValidIdentifier(t *testing.T) {
tests := []struct {
key string
want bool
}{
// Valid Identifiers
{"dotted", true},
{"dotted123", true},
{"_under_scores", true},
{"ಠ_ಠ", true},
// Invalid chars
{"is-quoted", false},
{"Definitely quoted!", false},
// Reserved words
{"true", false},
{"else", false},
{"null", false},
// Empty string
{"", false},
}
for _, test := range tests {
have := validIdentifier(test.key)
if have != test.want {
t.Errorf("Want %t for validIdentifier(%s); have %t", test.want, test.key, have)
}
}
}
func TestValidFirstRune(t *testing.T) {
tests := []struct {
in rune
want bool
}{
{'r', true},
{'ಠ', true},
{'4', false},
{'-', false},
}
for _, test := range tests {
have := validFirstRune(test.in)
if have != test.want {
t.Errorf("Want %t for validFirstRune(%#U); have %t", test.want, test.in, have)
}
}
}
func TestValidSecondaryRune(t *testing.T) {
tests := []struct {
in rune
want bool
}{
{'r', true},
{'ಠ', true},
{'4', true},
{'-', false},
}
for _, test := range tests {
have := validSecondaryRune(test.in)
if have != test.want {
t.Errorf("Want %t for validSecondaryRune(%#U); have %t", test.want, test.in, have)
}
}
}
func BenchmarkValidIdentifier(b *testing.B) {
for i := 0; i < b.N; i++ {
validIdentifier("must-be-quoted")
}
}
func BenchmarkValidIdentifierUnquoted(b *testing.B) {
for i := 0; i < b.N; i++ {
validIdentifier("canbeunquoted")
}
}
func BenchmarkValidIdentifierReserved(b *testing.B) {
for i := 0; i < b.N; i++ {
validIdentifier("function")
}
}
================================================
FILE: main.go
================================================
package main
import (
"bufio"
"bytes"
"encoding/json"
"flag"
"fmt"
"io"
"os"
"sort"
"strings"
"github.com/fatih/color"
"github.com/mattn/go-colorable"
"github.com/nwidger/jsoncolor"
"github.com/pkg/errors"
)
// Exit codes
const (
exitOK = iota
exitOpenFile
exitReadInput
exitFormStatements
exitFetchURL
exitParseStatements
exitJSONEncode
)
// Option bitfields
const (
optMonochrome = 1 << iota
optNoSort
optJSON
)
// Output colors
var (
strColor = color.New(color.FgYellow)
braceColor = color.New(color.FgMagenta)
bareColor = color.New(color.FgBlue, color.Bold)
numColor = color.New(color.FgRed)
boolColor = color.New(color.FgCyan)
)
// gronVersion stores the current gron version, set at build
// time with the ldflags -X option
var gronVersion = "dev"
// Default value that is set if proxy/noproxy variables is not specified.
// Cannot be an empty string, because an empty string explicitly deactivates the
// proxy.
var undefinedProxy = "-"
func init() {
flag.Usage = func() {
h := "Transform JSON (from a file, URL, or stdin) into discrete assignments to make it greppable\n\n"
h += "Usage:\n"
h += " gron [OPTIONS] [FILE|URL|-]\n\n"
h += "Options:\n"
h += " -u, --ungron Reverse the operation (turn assignments back into JSON)\n"
h += " -v, --values Print just the values of provided assignments\n"
h += " -c, --colorize Colorize output (default on tty)\n"
h += " -m, --monochrome Monochrome (don't colorize output)\n"
h += " -s, --stream Treat each line of input as a separate JSON object\n"
h += " -k, --insecure Disable certificate validation\n"
h += " -x, --proxy Set proxy configuration\n"
h += " --noproxy Comma-separated list of hosts for which not to use a proxy, if one is specified.\n"
h += " -j, --json Represent gron data as JSON stream\n"
h += " --no-sort Don't sort output (faster)\n"
h += " --version Print version information\n\n"
h += "Exit Codes:\n"
h += fmt.Sprintf(" %d\t%s\n", exitOK, "OK")
h += fmt.Sprintf(" %d\t%s\n", exitOpenFile, "Failed to open file")
h += fmt.Sprintf(" %d\t%s\n", exitReadInput, "Failed to read input")
h += fmt.Sprintf(" %d\t%s\n", exitFormStatements, "Failed to form statements")
h += fmt.Sprintf(" %d\t%s\n", exitFetchURL, "Failed to fetch URL")
h += fmt.Sprintf(" %d\t%s\n", exitParseStatements, "Failed to parse statements")
h += fmt.Sprintf(" %d\t%s\n", exitJSONEncode, "Failed to encode JSON")
h += "\n"
h += "Examples:\n"
h += " gron /tmp/apiresponse.json\n"
h += " gron http://jsonplaceholder.typicode.com/users/1 \n"
h += " curl -s http://jsonplaceholder.typicode.com/users/1 | gron\n"
h += " gron http://jsonplaceholder.typicode.com/users/1 | grep company | gron --ungron\n"
fmt.Fprint(os.Stderr, h)
}
}
func main() {
var (
ungronFlag bool
colorizeFlag bool
monochromeFlag bool
streamFlag bool
noSortFlag bool
versionFlag bool
insecureFlag bool
jsonFlag bool
valuesFlag bool
proxyURL string
noProxy string
)
flag.BoolVar(&ungronFlag, "ungron", false, "")
flag.BoolVar(&ungronFlag, "u", false, "")
flag.BoolVar(&colorizeFlag, "colorize", false, "")
flag.BoolVar(&colorizeFlag, "c", false, "")
flag.BoolVar(&monochromeFlag, "monochrome", false, "")
flag.BoolVar(&monochromeFlag, "m", false, "")
flag.BoolVar(&streamFlag, "s", false, "")
flag.BoolVar(&streamFlag, "stream", false, "")
flag.BoolVar(&noSortFlag, "no-sort", false, "")
flag.BoolVar(&versionFlag, "version", false, "")
flag.BoolVar(&insecureFlag, "k", false, "")
flag.BoolVar(&insecureFlag, "insecure", false, "")
flag.BoolVar(&jsonFlag, "j", false, "")
flag.BoolVar(&jsonFlag, "json", false, "")
flag.BoolVar(&valuesFlag, "values", false, "")
flag.BoolVar(&valuesFlag, "value", false, "")
flag.BoolVar(&valuesFlag, "v", false, "")
flag.StringVar(&proxyURL, "x", undefinedProxy, "")
flag.StringVar(&proxyURL, "proxy", undefinedProxy, "")
flag.StringVar(&noProxy, "noproxy", undefinedProxy, "")
flag.Parse()
// Print version information
if versionFlag {
fmt.Printf("gron version %s\n", gronVersion)
os.Exit(exitOK)
}
// If executed as 'ungron' set the --ungron flag
if strings.HasSuffix(os.Args[0], "ungron") {
ungronFlag = true
}
// Determine what the program's input should be:
// file, HTTP URL or stdin
var rawInput io.Reader
filename := flag.Arg(0)
if filename == "" || filename == "-" {
rawInput = os.Stdin
} else if validURL(filename) {
r, err := getURL(filename, insecureFlag, proxyURL, noProxy)
if err != nil {
fatal(exitFetchURL, err)
}
rawInput = r
} else {
r, err := os.Open(filename)
if err != nil {
fatal(exitOpenFile, err)
}
rawInput = r
}
var opts int
// The monochrome option should be forced if the output isn't a terminal
// to avoid doing unnecessary work calling the color functions
switch {
case colorizeFlag:
color.NoColor = false
case monochromeFlag || color.NoColor:
opts = opts | optMonochrome
}
if noSortFlag {
opts = opts | optNoSort
}
if jsonFlag {
opts = opts | optJSON
}
// Pick the appropriate action: gron, ungron, gronValues, or gronStream
var a actionFn = gron
if ungronFlag {
a = ungron
} else if valuesFlag {
a = gronValues
} else if streamFlag {
a = gronStream
}
exitCode, err := a(rawInput, colorable.NewColorableStdout(), opts)
if exitCode != exitOK {
fatal(exitCode, err)
}
os.Exit(exitOK)
}
// an actionFn represents a main action of the program, it accepts
// an input, output and a bitfield of options; returning an exit
// code and any error that occurred
type actionFn func(io.Reader, io.Writer, int) (int, error)
// gron is the default action. Given JSON as the input it returns a list
// of assignment statements. Possible options are optNoSort and optMonochrome
func gron(r io.Reader, w io.Writer, opts int) (int, error) {
var err error
var conv statementconv
if opts&optMonochrome > 0 {
conv = statementToString
} else {
conv = statementToColorString
}
ss, err := statementsFromJSON(r, statement{{"json", typBare}})
if err != nil {
goto out
}
// Go's maps do not have well-defined ordering, but we want a consistent
// output for a given input, so we must sort the statements
if opts&optNoSort == 0 {
sort.Sort(ss)
}
for _, s := range ss {
if opts&optJSON > 0 {
s, err = s.jsonify()
if err != nil {
goto out
}
}
fmt.Fprintln(w, conv(s))
}
out:
if err != nil {
return exitFormStatements, fmt.Errorf("failed to form statements: %s", err)
}
return exitOK, nil
}
// gronStream is like the gron action, but it treats the input as one
// JSON object per line. There's a bit of code duplication from the
// gron action, but it'd be fairly messy to combine the two actions
func gronStream(r io.Reader, w io.Writer, opts int) (int, error) {
var err error
errstr := "failed to form statements"
var i int
var sc *bufio.Scanner
var buf []byte
var conv func(s statement) string
if opts&optMonochrome > 0 {
conv = statementToString
} else {
conv = statementToColorString
}
// Helper function to make the prefix statements for each line
makePrefix := func(index int) statement {
return statement{
{"json", typBare},
{"[", typLBrace},
{fmt.Sprintf("%d", index), typNumericKey},
{"]", typRBrace},
}
}
// The first line of output needs to establish that the top-level
// thing is actually an array...
top := statement{
{"json", typBare},
{"=", typEquals},
{"[]", typEmptyArray},
{";", typSemi},
}
if opts&optJSON > 0 {
top, err = top.jsonify()
if err != nil {
goto out
}
}
fmt.Fprintln(w, conv(top))
// Read the input line by line
sc = bufio.NewScanner(r)
buf = make([]byte, 0, 64*1024)
sc.Buffer(buf, 1024*1024)
i = 0
for sc.Scan() {
line := bytes.NewBuffer(sc.Bytes())
var ss statements
ss, err = statementsFromJSON(line, makePrefix(i))
i++
if err != nil {
goto out
}
// Go's maps do not have well-defined ordering, but we want a consistent
// output for a given input, so we must sort the statements
if opts&optNoSort == 0 {
sort.Sort(ss)
}
for _, s := range ss {
if opts&optJSON > 0 {
s, err = s.jsonify()
if err != nil {
goto out
}
}
fmt.Fprintln(w, conv(s))
}
}
if err = sc.Err(); err != nil {
errstr = "error reading multiline input: %s"
}
out:
if err != nil {
return exitFormStatements, fmt.Errorf(errstr+": %s", err)
}
return exitOK, nil
}
// ungron is the reverse of gron. Given assignment statements as input,
// it returns JSON. The only option is optMonochrome
func ungron(r io.Reader, w io.Writer, opts int) (int, error) {
scanner := bufio.NewScanner(r)
var maker statementmaker
// Allow larger internal buffer of the scanner (min: 64KiB ~ max: 1MiB)
scanner.Buffer(make([]byte, 64*1024), 1024*1024)
if opts&optJSON > 0 {
maker = statementFromJSONSpec
} else {
maker = statementFromStringMaker
}
// Make a list of statements from the input
var ss statements
for scanner.Scan() {
s, err := maker(scanner.Text())
if err != nil {
return exitParseStatements, err
}
ss.add(s)
}
if err := scanner.Err(); err != nil {
return exitReadInput, fmt.Errorf("failed to read input statements")
}
// turn the statements into a single merged interface{} type
merged, err := ss.toInterface()
if err != nil {
return exitParseStatements, err
}
// If there's only one top level key and it's "json", make that the top level thing
mergedMap, ok := merged.(map[string]interface{})
if ok {
if len(mergedMap) == 1 {
if _, exists := mergedMap["json"]; exists {
merged = mergedMap["json"]
}
}
}
// Marshal the output into JSON to display to the user
out := &bytes.Buffer{}
enc := json.NewEncoder(out)
enc.SetIndent("", " ")
enc.SetEscapeHTML(false)
err = enc.Encode(merged)
if err != nil {
return exitJSONEncode, errors.Wrap(err, "failed to convert statements to JSON")
}
j := out.Bytes()
// If the output isn't monochrome, add color to the JSON
if opts&optMonochrome == 0 {
c, err := colorizeJSON(j)
// If we failed to colorize the JSON for whatever reason,
// we'll just fall back to monochrome output, otherwise
// replace the monochrome JSON with glorious technicolor
if err == nil {
j = c
}
}
// For whatever reason, the monochrome version of the JSON
// has a trailing newline character, but the colorized version
// does not. Strip the whitespace so that neither has the newline
// character on the end, and then we'll add a newline in the
// Fprintf below
j = bytes.TrimSpace(j)
fmt.Fprintf(w, "%s\n", j)
return exitOK, nil
}
// gronValues prints just the scalar values from some input gron statements
// without any quotes or anything of that sort; a bit like jq -r
// e.g. json[0].user.name = "Sam"; -> Sam
func gronValues(r io.Reader, w io.Writer, opts int) (int, error) {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
s := statementFromString(scanner.Text())
if len(s) == 0 {
return exitParseStatements, fmt.Errorf("failed to parse '%s' as gron statement", scanner.Text())
}
// strip off the leading 'json' bare key
if s[0].typ == typBare && s[0].text == "json" {
s = s[1:]
}
// strip off the leading dots
if s[0].typ == typDot || s[0].typ == typLBrace {
s = s[1:]
}
for _, t := range s {
switch t.typ {
case typString:
var text string
err := json.Unmarshal([]byte(t.text), &text)
if err != nil {
// just swallow errors and try to continue
continue
}
fmt.Println(text)
case typNumber, typTrue, typFalse, typNull:
fmt.Println(t.text)
default:
// Nothing
}
}
}
return exitOK, nil
}
func colorizeJSON(src []byte) ([]byte, error) {
out := &bytes.Buffer{}
f := jsoncolor.NewFormatter()
f.StringColor = strColor
f.ObjectColor = braceColor
f.ArrayColor = braceColor
f.FieldColor = bareColor
f.NumberColor = numColor
f.TrueColor = boolColor
f.FalseColor = boolColor
f.NullColor = boolColor
err := f.Format(out, src)
if err != nil {
return out.Bytes(), err
}
return out.Bytes(), nil
}
func fatal(code int, err error) {
fmt.Fprintf(os.Stderr, "%s\n", err)
os.Exit(code)
}
================================================
FILE: main_test.go
================================================
package main
import (
"bytes"
"encoding/json"
"io/ioutil"
"os"
"reflect"
"testing"
)
func TestGron(t *testing.T) {
cases := []struct {
inFile string
outFile string
}{
{"testdata/one.json", "testdata/one.gron"},
{"testdata/two.json", "testdata/two.gron"},
{"testdata/three.json", "testdata/three.gron"},
{"testdata/github.json", "testdata/github.gron"},
}
for _, c := range cases {
in, err := os.Open(c.inFile)
if err != nil {
t.Fatalf("failed to open input file: %s", err)
}
want, err := ioutil.ReadFile(c.outFile)
if err != nil {
t.Fatalf("failed to open want file: %s", err)
}
out := &bytes.Buffer{}
code, err := gron(in, out, optMonochrome)
if code != exitOK {
t.Errorf("want exitOK; have %d", code)
}
if err != nil {
t.Errorf("want nil error; have %s", err)
}
if !reflect.DeepEqual(want, out.Bytes()) {
t.Logf("want: %s", want)
t.Logf("have: %s", out.Bytes())
t.Errorf("gronned %s does not match %s", c.inFile, c.outFile)
}
}
}
func TestGronStream(t *testing.T) {
cases := []struct {
inFile string
outFile string
}{
{"testdata/stream.json", "testdata/stream.gron"},
{"testdata/scalar-stream.json", "testdata/scalar-stream.gron"},
}
for _, c := range cases {
in, err := os.Open(c.inFile)
if err != nil {
t.Fatalf("failed to open input file: %s", err)
}
want, err := ioutil.ReadFile(c.outFile)
if err != nil {
t.Fatalf("failed to open want file: %s", err)
}
out := &bytes.Buffer{}
code, err := gronStream(in, out, optMonochrome)
if code != exitOK {
t.Errorf("want exitOK; have %d", code)
}
if err != nil {
t.Errorf("want nil error; have %s", err)
}
if !reflect.DeepEqual(want, out.Bytes()) {
t.Logf("want: %s", want)
t.Logf("have: %s", out.Bytes())
t.Errorf("gronned %s does not match %s", c.inFile, c.outFile)
}
}
}
func TestLargeGronStream(t *testing.T) {
cases := []struct {
inFile string
outFile string
}{
{"testdata/long-stream.json", "testdata/long-stream.gron"},
}
for _, c := range cases {
in, err := os.Open(c.inFile)
if err != nil {
t.Fatalf("failed to open input file: %s", err)
}
want, err := ioutil.ReadFile(c.outFile)
if err != nil {
t.Fatalf("failed to open want file: %s", err)
}
out := &bytes.Buffer{}
code, err := gronStream(in, out, optMonochrome)
if code != exitOK {
t.Errorf("want exitOK; have %d", code)
}
if err != nil {
t.Errorf("want nil error; have %s", err)
}
if !reflect.DeepEqual(want, out.Bytes()) {
t.Logf("want: %s", want)
t.Logf("have: %s", out.Bytes())
t.Errorf("gronned %s does not match %s", c.inFile, c.outFile)
}
}
}
func TestUngron(t *testing.T) {
cases := []struct {
inFile string
outFile string
}{
{"testdata/one.gron", "testdata/one.json"},
{"testdata/two.gron", "testdata/two.json"},
{"testdata/three.gron", "testdata/three.json"},
{"testdata/grep-separators.gron", "testdata/grep-separators.json"},
{"testdata/github.gron", "testdata/github.json"},
{"testdata/large-line.gron", "testdata/large-line.json"},
}
for _, c := range cases {
wantF, err := ioutil.ReadFile(c.outFile)
if err != nil {
t.Fatalf("failed to open want file: %s", err)
}
var want interface{}
err = json.Unmarshal(wantF, &want)
if err != nil {
t.Fatalf("failed to unmarshal JSON from want file: %s", err)
}
in, err := os.Open(c.inFile)
if err != nil {
t.Fatalf("failed to open input file: %s", err)
}
out := &bytes.Buffer{}
code, err := ungron(in, out, optMonochrome)
if code != exitOK {
t.Errorf("want exitOK; have %d", code)
}
if err != nil {
t.Errorf("want nil error; have %s", err)
}
var have interface{}
err = json.Unmarshal(out.Bytes(), &have)
if err != nil {
t.Fatalf("failed to unmarshal JSON from ungron output: %s", err)
}
if !reflect.DeepEqual(want, have) {
t.Logf("want: %#v", want)
t.Logf("have: %#v", have)
t.Errorf("ungronned %s does not match %s", c.inFile, c.outFile)
}
}
}
func TestGronJ(t *testing.T) {
cases := []struct {
inFile string
outFile string
}{
{"testdata/one.json", "testdata/one.jgron"},
{"testdata/two.json", "testdata/two.jgron"},
{"testdata/three.json", "testdata/three.jgron"},
{"testdata/github.json", "testdata/github.jgron"},
}
for _, c := range cases {
in, err := os.Open(c.inFile)
if err != nil {
t.Fatalf("failed to open input file: %s", err)
}
want, err := ioutil.ReadFile(c.outFile)
if err != nil {
t.Fatalf("failed to open want file: %s", err)
}
out := &bytes.Buffer{}
code, err := gron(in, out, optMonochrome|optJSON)
if code != exitOK {
t.Errorf("want exitOK; have %d", code)
}
if err != nil {
t.Errorf("want nil error; have %s", err)
}
if !reflect.DeepEqual(want, out.Bytes()) {
t.Logf("want: %s", want)
t.Logf("have: %s", out.Bytes())
t.Errorf("gronned %s does not match %s", c.inFile, c.outFile)
}
}
}
func TestGronStreamJ(t *testing.T) {
cases := []struct {
inFile string
outFile string
}{
{"testdata/stream.json", "testdata/stream.jgron"},
{"testdata/scalar-stream.json", "testdata/scalar-stream.jgron"},
}
for _, c := range cases {
in, err := os.Open(c.inFile)
if err != nil {
t.Fatalf("failed to open input file: %s", err)
}
want, err := ioutil.ReadFile(c.outFile)
if err != nil {
t.Fatalf("failed to open want file: %s", err)
}
out := &bytes.Buffer{}
code, err := gronStream(in, out, optMonochrome|optJSON)
if code != exitOK {
t.Errorf("want exitOK; have %d", code)
}
if err != nil {
t.Errorf("want nil error; have %s", err)
}
if !reflect.DeepEqual(want, out.Bytes()) {
t.Logf("want: %s", want)
t.Logf("have: %s", out.Bytes())
t.Errorf("gronned %s does not match %s", c.inFile, c.outFile)
}
}
}
func TestUngronJ(t *testing.T) {
cases := []struct {
inFile string
outFile string
}{
{"testdata/one.jgron", "testdata/one.json"},
{"testdata/two.jgron", "testdata/two.json"},
{"testdata/three.jgron", "testdata/three.json"},
{"testdata/github.jgron", "testdata/github.json"},
}
for _, c := range cases {
wantF, err := ioutil.ReadFile(c.outFile)
if err != nil {
t.Fatalf("failed to open want file: %s", err)
}
var want interface{}
err = json.Unmarshal(wantF, &want)
if err != nil {
t.Fatalf("failed to unmarshal JSON from want file: %s", err)
}
in, err := os.Open(c.inFile)
if err != nil {
t.Fatalf("failed to open input file: %s", err)
}
out := &bytes.Buffer{}
code, err := ungron(in, out, optMonochrome|optJSON)
if code != exitOK {
t.Errorf("want exitOK; have %d", code)
}
if err != nil {
t.Errorf("want nil error; have %s", err)
}
var have interface{}
err = json.Unmarshal(out.Bytes(), &have)
if err != nil {
t.Fatalf("failed to unmarshal JSON from ungron output: %s", err)
}
if !reflect.DeepEqual(want, have) {
t.Logf("want: %#v", want)
t.Logf("have: %#v", have)
t.Errorf("ungronned %s does not match %s", c.inFile, c.outFile)
}
}
}
func BenchmarkBigJSON(b *testing.B) {
in, err := os.Open("testdata/big.json")
if err != nil {
b.Fatalf("failed to open test data file: %s", err)
}
for i := 0; i < b.N; i++ {
out := &bytes.Buffer{}
_, err = in.Seek(0, 0)
if err != nil {
b.Fatalf("failed to rewind input: %s", err)
}
_, err := gron(in, out, optMonochrome|optNoSort)
if err != nil {
b.Fatalf("failed to gron: %s", err)
}
}
}
================================================
FILE: original-gron.php
================================================
#!/usr/bin/env php
<?php
//////////
// Gron //
//////////
// Take valid JSON on stdin, or read it from a file or URL,
// then output it as discrete assignments to make it grep-able.
// Exit codes:
// 0 - Success
// 1 - Failed to decode JSON
// 2 - Argument is not valid file or URL
// 3 - Failed to fetch data from URL
// Tom Hudson - 2012
// https://github.com/TomNomNom/gron
// Decide on stdin, a local file or URL
if ($argc == 1){
$buffer = file_get_contents('php://stdin');
} else {
$source = $argv[1];
// Check for a readable file or URL
if (is_readable($source)){
$buffer = file_get_contents($source);
} else if (filter_var($source, FILTER_VALIDATE_URL)){
$c = curl_init($source);
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($c, CURLOPT_TIMEOUT, 20);
curl_setopt($c, CURLOPT_HTTPHEADER, array(
'Accept: application/json'
));
$buffer = curl_exec($c);
$err = curl_errno($c);
curl_close($c);
if ($err != CURLE_OK){
fputs(STDERR, "Data could not be fetched from [{$source}]\n");
exit(3);
}
} else {
fputs(STDERR, "[{$source}] is not a valid file or URL.\n");
exit(2);
}
}
// Meat
$struct = json_decode($buffer);
$err = json_last_error();
if ($err != JSON_ERROR_NONE){
// Attempt to read as multiple lines of JSON (sometimes found in streaming APIs etc)
$lines = explode("\n", trim($buffer));
for ($i = 0; $i < sizeOf($lines); $i++){
$line = $lines[$i];
$struct = json_decode($line);
$err = json_last_error();
// No dice; time to die
if ($err != JSON_ERROR_NONE){
fputs(STDERR, "Failed to decode JSON\n");
exit(1);
}
printSruct($struct, "json{$i}");
echo PHP_EOL;
}
} else {
// Buffer is all one JSON blob
printSruct($struct);
}
function printSruct($struct, $prefix = 'json'){
if (is_object($struct)){
echo "{$prefix} = {};\n";
} elseif (is_array($struct)){
echo "{$prefix} = [];\n";
} else {
echo "{$prefix} = ". json_encode($struct) .";\n";
// No need to iterate if we already have a scalar
return;
}
foreach ($struct as $k => $v){
$k = json_encode($k);
printSruct($v, "{$prefix}[{$k}]");
}
}
exit(0);
================================================
FILE: script/example
================================================
#!/bin/sh
PROJDIR=$(cd `dirname $0`/.. && pwd)
cd $PROJDIR
go build
./gron testdata/one.json
================================================
FILE: script/lint
================================================
#!/bin/sh
PROJDIR=$(cd `dirname $0`/.. && pwd)
cd ${PROJDIR}
which gometalinter > /dev/null
if [ $? -ne 0 ]; then
echo "You don't have gometalinter. Installing it..."
go get github.com/alecthomas/gometalinter
gometalinter --install
fi
# dupl is disabled because it has a habbit of identifying tests as duplicated code.
# in its defence: it's right. gocyclo is disabled because I'm a terrible programmer.
# gas is disabled because it doesn't like InsecureSkipVerify set to true for HTTP
# requests - but we only do that if the user asks for it.
gometalinter --disable=gocyclo --disable=dupl --enable=goimports --disable=gas
================================================
FILE: script/precommit
================================================
#!/bin/sh
set -e
PROJDIR=$(cd `dirname $0`/.. && pwd)
cd ${PROJDIR}
./script/test
================================================
FILE: script/profile
================================================
#!/bin/sh
set -e
PROJDIR=$(cd `dirname $0`/.. && pwd)
cd ${PROJDIR}
PAT="."
if [ ! -z "${1}" ]; then
PAT="${1}"
fi
go test -bench ${PAT} -benchmem -cpuprofile cpu.out
go tool pprof gron.test cpu.out
================================================
FILE: script/release
================================================
#!/bin/bash
PROJDIR=$(cd `dirname $0`/.. && pwd)
VERSION="${1}"
TAG="v${VERSION}"
USER="tomnomnom"
REPO="gron"
BINARY="${REPO}"
if [[ -z "${VERSION}" ]]; then
echo "Usage: ${0} <version>"
exit 1
fi
if [[ -z "${GITHUB_TOKEN}" ]]; then
echo "You forgot to set your GITHUB_TOKEN"
exit 2
fi
cd ${PROJDIR}
# Run the tests
go test
if [ $? -ne 0 ]; then
echo "Tests failed. Aborting."
exit 3
fi
FILELIST=""
for ARCH in "amd64" "386" "arm64" "arm"; do
for OS in "darwin" "linux" "windows" "freebsd"; do
if [[ "${OS}" == "darwin" && ("${ARCH}" == "386" || "${ARCH}" == "arm") ]]; then
continue
fi
BINFILE="${BINARY}"
if [[ "${OS}" == "windows" ]]; then
BINFILE="${BINFILE}.exe"
fi
rm -f ${BINFILE}
GOOS=${OS} GOARCH=${ARCH} go build -ldflags "-X main.gronVersion=${VERSION}" github.com/${USER}/${REPO}
if [[ "${OS}" == "windows" ]]; then
ARCHIVE="${BINARY}-${OS}-${ARCH}-${VERSION}.zip"
zip ${ARCHIVE} ${BINFILE}
rm ${BINFILE}
else
ARCHIVE="${BINARY}-${OS}-${ARCH}-${VERSION}.tgz"
tar --create --gzip --file=${ARCHIVE} ${BINFILE}
fi
FILELIST="${FILELIST} ${PROJDIR}/${ARCHIVE}"
done
done
gh release create ${TAG} ${FILELIST}
rm ${FILELIST}
================================================
FILE: script/test
================================================
#!/bin/sh
PROJDIR=$(cd `dirname $0`/.. && pwd)
cd ${PROJDIR}
go test
================================================
FILE: statements.go
================================================
package main
import (
"encoding/json"
"fmt"
"io"
"reflect"
"strconv"
"strings"
"github.com/pkg/errors"
)
// A statement is a slice of tokens representing an assignment statement.
// An assignment statement is something like:
//
// json.city = "Leeds";
//
// Where 'json', '.', 'city', '=', '"Leeds"' and ';' are discrete tokens.
// Statements are stored as tokens to make sorting more efficient, and so
// that the same type can easily be used when gronning and ungronning.
type statement []token
// String returns the string form of a statement rather than the
// underlying slice of tokens
func (s statement) String() string {
out := make([]string, 0, len(s)+2)
for _, t := range s {
out = append(out, t.format())
}
return strings.Join(out, "")
}
// colorString returns the string form of a statement with ASCII color codes
func (s statement) colorString() string {
out := make([]string, 0, len(s)+2)
for _, t := range s {
out = append(out, t.formatColor())
}
return strings.Join(out, "")
}
// a statementconv converts a statement to string
type statementconv func(s statement) string
// statementconv variant of statement.String
func statementToString(s statement) string {
return s.String()
}
// statementconv variant of statement.colorString
func statementToColorString(s statement) string {
return s.colorString()
}
// withBare returns a copy of a statement with a new bare
// word token appended to it
func (s statement) withBare(k string) statement {
new := make(statement, len(s), len(s)+2)
copy(new, s)
return append(
new,
token{".", typDot},
token{k, typBare},
)
}
// jsonify converts an assignment statement to a JSON representation
func (s statement) jsonify() (statement, error) {
// If m is the number of keys occurring in the left hand side
// of s, then len(s) is in between 2*m+4 and 3*m+4. The resultant
// statement j (carrying the JSON representation) is always 2*m+5
// long. So len(s)+1 ≥ 2*m+5 = len(j). Therefore an initaial
// allocation of j with capacity len(s)+1 will allow us to carry
// through without reallocation.
j := make(statement, 0, len(s)+1)
if len(s) < 4 || s[0].typ != typBare || s[len(s)-3].typ != typEquals ||
s[len(s)-1].typ != typSemi {
return nil, errors.New("non-assignment statement")
}
j = append(j, token{"[", typLBrace})
j = append(j, token{"[", typLBrace})
for _, t := range s[1 : len(s)-3] {
switch t.typ {
case typNumericKey, typQuotedKey:
j = append(j, t)
j = append(j, token{",", typComma})
case typBare:
j = append(j, token{quoteString(t.text), typQuotedKey})
j = append(j, token{",", typComma})
}
}
if j[len(j)-1].typ == typComma {
j = j[:len(j)-1]
}
j = append(j, token{"]", typLBrace})
j = append(j, token{",", typComma})
j = append(j, s[len(s)-2])
j = append(j, token{"]", typLBrace})
return j, nil
}
// withQuotedKey returns a copy of a statement with a new
// quoted key token appended to it
func (s statement) withQuotedKey(k string) statement {
new := make(statement, len(s), len(s)+3)
copy(new, s)
return append(
new,
token{"[", typLBrace},
token{quoteString(k), typQuotedKey},
token{"]", typRBrace},
)
}
// withNumericKey returns a copy of a statement with a new
// numeric key token appended to it
func (s statement) withNumericKey(k int) statement {
new := make(statement, len(s), len(s)+3)
copy(new, s)
return append(
new,
token{"[", typLBrace},
token{strconv.Itoa(k), typNumericKey},
token{"]", typRBrace},
)
}
// statements is a list of assignment statements.
// E.g statement: json.foo = "bar";
type statements []statement
// addWithValue takes a statement representing a path, copies it,
// adds a value token to the end of the statement and appends
// the new statement to the list of statements
func (ss *statements) addWithValue(path statement, value token) {
s := make(statement, len(path), len(path)+3)
copy(s, path)
s = append(s, token{"=", typEquals}, value, token{";", typSemi})
*ss = append(*ss, s)
}
// add appends a new complete statement to list of statements
func (ss *statements) add(s statement) {
*ss = append(*ss, s)
}
// Len returns the number of statements for sort.Sort
func (ss statements) Len() int {
return len(ss)
}
// Swap swaps two statements for sort.Sort
func (ss statements) Swap(i, j int) {
ss[i], ss[j] = ss[j], ss[i]
}
// a statementmaker is a function that makes a statement
// from string
type statementmaker func(str string) (statement, error)
// statementFromString takes statement string, lexes it and returns
// the corresponding statement
func statementFromString(str string) statement {
l := newLexer(str)
s := l.lex()
return s
}
// statementmaker variant of statementFromString
func statementFromStringMaker(str string) (statement, error) {
return statementFromString(str), nil
}
// statementFromJson returns statement encoded by
// JSON specification
func statementFromJSONSpec(str string) (statement, error) {
var a []interface{}
var ok bool
var v interface{}
var s statement
var t tokenTyp
var nstr string
var nbuf []byte
err := json.Unmarshal([]byte(str), &a)
if err != nil {
return nil, err
}
if len(a) != 2 {
goto out
}
v = a[1]
a, ok = a[0].([]interface{})
if !ok {
goto out
}
// We'll append one initial token, then 3 tokens for each element of a,
// then 3 closing tokens, that's alltogether 3*len(a)+4.
s = make(statement, 0, 3*len(a)+4)
s = append(s, token{"json", typBare})
for _, e := range a {
s = append(s, token{"[", typLBrace})
switch e := e.(type) {
case string:
s = append(s, token{quoteString(e), typQuotedKey})
case float64:
nbuf, err = json.Marshal(e)
if err != nil {
return nil, errors.Wrap(err, "JSON internal error")
}
nstr = string(nbuf)
s = append(s, token{nstr, typNumericKey})
default:
ok = false
goto out
}
s = append(s, token{"]", typRBrace})
}
s = append(s, token{"=", typEquals})
switch v := v.(type) {
case bool:
if v {
t = typTrue
} else {
t = typFalse
}
case float64:
t = typNumber
case string:
t = typString
case []interface{}:
ok = (len(v) == 0)
if !ok {
goto out
}
t = typEmptyArray
case map[string]interface{}:
ok = (len(v) == 0)
if !ok {
goto out
}
t = typEmptyObject
default:
ok = (v == nil)
if !ok {
goto out
}
t = typNull
}
nbuf, err = json.Marshal(v)
if err != nil {
return nil, errors.Wrap(err, "JSON internal error")
}
nstr = string(nbuf)
s = append(s, token{nstr, t})
s = append(s, token{";", typSemi})
out:
if !ok {
return nil, errors.New("invalid JSON layout")
}
return s, nil
}
// ungron turns statements into a proper datastructure
func (ss statements) toInterface() (interface{}, error) {
// Get all the individually parsed statements
var parsed []interface{}
for _, s := range ss {
u, err := ungronTokens(s)
switch err.(type) {
case nil:
// no problem :)
case errRecoverable:
continue
default:
return nil, errors.Wrapf(err, "ungron failed for `%s`", s)
}
parsed = append(parsed, u)
}
if len(parsed) == 0 {
return nil, fmt.Errorf("no statements were parsed")
}
merged := parsed[0]
for _, p := range parsed[1:] {
m, err := recursiveMerge(merged, p)
if err != nil {
return nil, errors.Wrap(err, "failed to merge statements")
}
merged = m
}
return merged, nil
}
// Less compares two statements for sort.Sort
// Implements a natural sort to keep array indexes in order
func (ss statements) Less(a, b int) bool {
// ss[a] and ss[b] are both slices of tokens. The first
// thing we need to do is find the first token (if any)
// that differs, then we can use that token to decide
// if ss[a] or ss[b] should come first in the sort.
diffIndex := -1
for i := range ss[a] {
if len(ss[b]) < i+1 {
// b must be shorter than a, so it
// should come first
return false
}
// The tokens match, so just carry on
if ss[a][i] == ss[b][i] {
continue
}
// We've found a difference
diffIndex = i
break
}
// If diffIndex is still -1 then the only difference must be
// that ss[b] is longer than ss[a], so ss[a] should come first
if diffIndex == -1 {
return true
}
// Get the tokens that differ
ta := ss[a][diffIndex]
tb := ss[b][diffIndex]
// An equals always comes first
if ta.typ == typEquals {
return true
}
if tb.typ == typEquals {
return false
}
// If both tokens are numeric keys do an integer comparison
if ta.typ == typNumericKey && tb.typ == typNumericKey {
ia, _ := strconv.Atoi(ta.text)
ib, _ := strconv.Atoi(tb.text)
return ia < ib
}
// If neither token is a number, just do a string comparison
if ta.typ != typNumber || tb.typ != typNumber {
return ta.text < tb.text
}
// We have two numbers to compare so turn them into json.Number
// for comparison
na, _ := json.Number(ta.text).Float64()
nb, _ := json.Number(tb.text).Float64()
return na < nb
}
// Contains searches the statements for a given statement
// Mostly to make testing things easier
func (ss statements) Contains(search statement) bool {
for _, i := range ss {
if reflect.DeepEqual(i, search) {
return true
}
}
return false
}
// statementsFromJSON takes an io.Reader containing JSON
// and returns statements or an error on failure
func statementsFromJSON(r io.Reader, prefix statement) (statements, error) {
var top interface{}
d := json.NewDecoder(r)
d.UseNumber()
err := d.Decode(&top)
if err != nil {
return nil, err
}
ss := make(statements, 0, 32)
ss.fill(prefix, top)
return ss, nil
}
// fill takes a prefix statement and some value and recursively fills
// the statement list using that value
func (ss *statements) fill(prefix statement, v interface{}) {
// Add a statement for the current prefix and value
ss.addWithValue(prefix, valueTokenFromInterface(v))
// Recurse into objects and arrays
switch vv := v.(type) {
case map[string]interface{}:
// It's an object
for k, sub := range vv {
if validIdentifier(k) {
ss.fill(prefix.withBare(k), sub)
} else {
ss.fill(prefix.withQuotedKey(k), sub)
}
}
case []interface{}:
// It's an array
for k, sub := range vv {
ss.fill(prefix.withNumericKey(k), sub)
}
}
}
================================================
FILE: statements_test.go
================================================
package main
import (
"bytes"
"encoding/json"
"reflect"
"sort"
"testing"
)
func statementsFromStringSlice(strs []string) statements {
ss := make(statements, len(strs))
for i, str := range strs {
ss[i] = statementFromString(str)
}
return ss
}
func TestStatementsSimple(t *testing.T) {
j := []byte(`{
"dotted": "A dotted value",
"a quoted": "value",
"bool1": true,
"bool2": false,
"anull": null,
"anarr": [1, 1.5],
"anob": {
"foo": "bar"
},
"else": 1,
"id": 66912849,
"": 2
}`)
ss, err := statementsFromJSON(bytes.NewReader(j), statement{{"json", typBare}})
if err != nil {
t.Errorf("Want nil error from makeStatementsFromJSON() but got %s", err)
}
wants := statementsFromStringSlice([]string{
`json = {};`,
`json.dotted = "A dotted value";`,
`json["a quoted"] = "value";`,
`json.bool1 = true;`,
`json.bool2 = false;`,
`json.anull = null;`,
`json.anarr = [];`,
`json.anarr[0] = 1;`,
`json.anarr[1] = 1.5;`,
`json.anob = {};`,
`json.anob.foo = "bar";`,
`json["else"] = 1;`,
`json.id = 66912849;`,
`json[""] = 2;`,
})
t.Logf("Have: %#v", ss)
for _, want := range wants {
if !ss.Contains(want) {
t.Errorf("Statement group should contain `%s` but doesn't", want)
}
}
}
func TestStatementsSorting(t *testing.T) {
want := statementsFromStringSlice([]string{
`json.a = true;`,
`json.b = true;`,
`json.c[0] = true;`,
`json.c[2] = true;`,
`json.c[10] = true;`,
`json.c[11] = true;`,
`json.c[21][2] = true;`,
`json.c[21][11] = true;`,
})
have := statementsFromStringSlice([]string{
`json.c[11] = true;`,
`json.c[21][2] = true;`,
`json.c[0] = true;`,
`json.c[2] = true;`,
`json.b = true;`,
`json.c[10] = true;`,
`json.c[21][11] = true;`,
`json.a = true;`,
})
sort.Sort(have)
for i := range want {
if !reflect.DeepEqual(have[i], want[i]) {
t.Errorf("Statements sorted incorrectly; want `%s` at index %d, have `%s`", want[i], i, have[i])
}
}
}
func BenchmarkStatementsLess(b *testing.B) {
ss := statementsFromStringSlice([]string{
`json.c[21][2] = true;`,
`json.c[21][11] = true;`,
})
for i := 0; i < b.N; i++ {
_ = ss.Less(0, 1)
}
}
func BenchmarkFill(b *testing.B) {
j := []byte(`{
"dotted": "A dotted value",
"a quoted": "value",
"bool1": true,
"bool2": false,
"anull": null,
"anarr": [1, 1.5],
"anob": {
"foo": "bar"
},
"else": 1
}`)
var top interface{}
err := json.Unmarshal(j, &top)
if err != nil {
b.Fatalf("Failed to unmarshal test file: %s", err)
}
for i := 0; i < b.N; i++ {
ss := make(statements, 0)
ss.fill(statement{{"json", typBare}}, top)
}
}
func TestUngronStatementsSimple(t *testing.T) {
in := statementsFromStringSlice([]string{
`json.contact = {};`,
`json.contact["e-mail"][0] = "mail@tomnomnom.com";`,
`json.contact["e-mail"][1] = "test@tomnomnom.com";`,
`json.contact["e-mail"][3] = "foo@tomnomnom.com";`,
`json.contact.twitter = "@TomNomNom";`,
})
want := map[string]interface{}{
"json": map[string]interface{}{
"contact": map[string]interface{}{
"e-mail": []interface{}{
0: "mail@tomnomnom.com",
1: "test@tomnomnom.com",
3: "foo@tomnomnom.com",
},
"twitter": "@TomNomNom",
},
},
}
have, err := in.toInterface()
if err != nil {
t.Fatalf("want nil error but have: %s", err)
}
t.Logf("Have: %#v", have)
t.Logf("Want: %#v", want)
eq := reflect.DeepEqual(have, want)
if !eq {
t.Errorf("have and want are not equal")
}
}
func TestUngronStatementsInvalid(t *testing.T) {
cases := []statements{
statementsFromStringSlice([]string{``}),
statementsFromStringSlice([]string{`this isn't a statement at all`}),
statementsFromStringSlice([]string{`json[0] = 1;`, `json.bar = 1;`}),
}
for _, c := range cases {
_, err := c.toInterface()
if err == nil {
t.Errorf("want non-nil error; have nil")
}
}
}
func TestStatement(t *testing.T) {
s := statement{
token{"json", typBare},
token{".", typDot},
token{"foo", typBare},
token{"=", typEquals},
token{"2", typNumber},
token{";", typSemi},
}
have := s.String()
want := "json.foo = 2;"
if have != want {
t.Errorf("have: `%s` want: `%s`", have, want)
}
}
================================================
FILE: testdata/big.json
================================================
[
{
"_id": "57d068e074bf05b8a0905846",
"index": 0,
"guid": "45c7a641-b187-45a6-b1e5-dbd5dd00d88e",
"isActive": false,
"balance": "$2,614.63",
"picture": "http://placehold.it/32x32",
"age": 37,
"eyeColor": "green",
"name": "Hollie Black",
"gender": "female",
"company": "MAGNEMO",
"email": "hollieblack@magnemo.com",
"phone": "+1 (861) 584-2364",
"address": "703 Eckford Street, Biddle, Rhode Island, 9242",
"about": "Aliqua laborum exercitation exercitation nisi laborum in id magna commodo ipsum officia laborum irure. Proident reprehenderit aliqua officia deserunt occaecat nostrud consectetur occaecat eu elit Lorem. Qui incididunt pariatur voluptate amet sit mollit nisi sunt excepteur culpa officia. Ut enim ipsum laborum laboris.\r\n",
"registered": "2015-07-21T11:03:52 -01:00",
"latitude": -43.154152,
"longitude": -47.976724,
"tags": [
"sit",
"fugiat",
"deserunt",
"est",
"mollit",
"qui",
"anim"
],
"friends": [
{
"id": 0,
"name": "Everett Spears"
},
{
"id": 1,
"name": "Alston Gaines"
},
{
"id": 2,
"name": "Crawford Wall"
}
],
"greeting": "Hello, Hollie Black! You have 9 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0c72d4287d63413b3",
"index": 1,
"guid": "a51f7543-7a19-4933-8bb2-1f17fa7ff342",
"isActive": true,
"balance": "$1,951.71",
"picture": "http://placehold.it/32x32",
"age": 22,
"eyeColor": "green",
"name": "Marilyn Mills",
"gender": "female",
"company": "GLUKGLUK",
"email": "marilynmills@glukgluk.com",
"phone": "+1 (878) 438-3363",
"address": "443 Montauk Avenue, Galesville, New Jersey, 9592",
"about": "Veniam excepteur officia ullamco adipisicing est eiusmod amet Lorem in ad. Laborum laboris eu id ut minim deserunt aliqua aliqua. Irure incididunt eiusmod enim qui laborum ea velit aute ex. Est minim in labore incididunt pariatur aliquip aute cillum esse adipisicing nostrud ea occaecat mollit. Deserunt est officia aliquip amet nulla eiusmod irure.\r\n",
"registered": "2014-04-22T06:14:31 -01:00",
"latitude": 46.640382,
"longitude": -118.066872,
"tags": [
"proident",
"excepteur",
"consequat",
"consequat",
"voluptate",
"culpa",
"ut"
],
"friends": [
{
"id": 0,
"name": "Mcneil Walter"
},
{
"id": 1,
"name": "Lloyd Cole"
},
{
"id": 2,
"name": "Vega Harding"
}
],
"greeting": "Hello, Marilyn Mills! You have 8 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e005f71541b88a0ef8",
"index": 2,
"guid": "f82d8c13-3e20-4ce9-814a-978dfa0382b1",
"isActive": false,
"balance": "$3,213.19",
"picture": "http://placehold.it/32x32",
"age": 22,
"eyeColor": "blue",
"name": "Mcfarland Thompson",
"gender": "male",
"company": "VOLAX",
"email": "mcfarlandthompson@volax.com",
"phone": "+1 (869) 472-3537",
"address": "651 Suydam Place, Hatteras, North Carolina, 1390",
"about": "Quis ipsum cupidatat commodo excepteur nulla ex irure anim commodo nisi aliqua fugiat. Dolore ut nulla labore amet tempor voluptate ea. Tempor deserunt in aute ullamco enim excepteur anim occaecat tempor nostrud non ex nulla laboris. Deserunt aliquip ipsum mollit culpa amet Lorem nisi sunt esse esse ut laborum nulla. Consequat eu ex dolore laborum consequat sint in amet ipsum cillum quis commodo proident. Sunt ex excepteur cillum elit cillum pariatur adipisicing laborum quis ullamco non.\r\n",
"registered": "2015-02-09T08:37:46 -00:00",
"latitude": 31.758534,
"longitude": -81.699786,
"tags": [
"Lorem",
"nostrud",
"tempor",
"ullamco",
"Lorem",
"aliquip",
"id"
],
"friends": [
{
"id": 0,
"name": "Sandoval Macdonald"
},
{
"id": 1,
"name": "Hudson Weaver"
},
{
"id": 2,
"name": "Ellison Stephens"
}
],
"greeting": "Hello, Mcfarland Thompson! You have 7 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e02f4d470fda5db0d8",
"index": 3,
"guid": "d7fc5b16-67e3-4e8b-98a8-ffb021ae86a7",
"isActive": false,
"balance": "$3,862.73",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "blue",
"name": "Holloway Bonner",
"gender": "male",
"company": "QUAILCOM",
"email": "hollowaybonner@quailcom.com",
"phone": "+1 (840) 597-3996",
"address": "105 Prescott Place, Washington, Massachusetts, 4998",
"about": "Ad occaecat consequat nisi id eu ullamco excepteur sit fugiat. Dolor tempor ipsum elit officia voluptate eiusmod enim. Veniam magna sunt laborum laborum voluptate sunt Lorem id tempor sint.\r\n",
"registered": "2014-09-27T07:12:29 -01:00",
"latitude": -0.859743,
"longitude": 114.294223,
"tags": [
"ad",
"laborum",
"enim",
"irure",
"sunt",
"incididunt",
"ad"
],
"friends": [
{
"id": 0,
"name": "Cathy Velasquez"
},
{
"id": 1,
"name": "Mclaughlin Pitts"
},
{
"id": 2,
"name": "Macdonald Wagner"
}
],
"greeting": "Hello, Holloway Bonner! You have 1 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0e8d9891bb488dda1",
"index": 4,
"guid": "9b4393b6-1fa5-48ab-af75-6c7abdaff58f",
"isActive": false,
"balance": "$1,189.99",
"picture": "http://placehold.it/32x32",
"age": 35,
"eyeColor": "brown",
"name": "Jenny Gomez",
"gender": "female",
"company": "CABLAM",
"email": "jennygomez@cablam.com",
"phone": "+1 (810) 488-2849",
"address": "914 Joralemon Street, Matthews, Palau, 9243",
"about": "Irure qui occaecat do non duis nisi nisi laborum deserunt enim laborum dolor consectetur. Nisi quis do officia labore deserunt reprehenderit laboris elit proident do nostrud. Magna consequat enim commodo id cupidatat aliquip deserunt do consequat pariatur voluptate. Reprehenderit aliqua consequat consequat culpa aliquip et eu aute proident ullamco dolore ipsum anim. Amet laboris aute cupidatat duis in consectetur fugiat.\r\n",
"registered": "2016-01-18T10:40:00 -00:00",
"latitude": -38.543452,
"longitude": 177.969015,
"tags": [
"amet",
"nulla",
"in",
"esse",
"magna",
"do",
"excepteur"
],
"friends": [
{
"id": 0,
"name": "Adrienne Jordan"
},
{
"id": 1,
"name": "Howell Erickson"
},
{
"id": 2,
"name": "Gina Prince"
}
],
"greeting": "Hello, Jenny Gomez! You have 6 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0cc62e68260fdb47c",
"index": 5,
"guid": "0491669d-4647-4b6e-b577-80f701d630f3",
"isActive": false,
"balance": "$2,162.74",
"picture": "http://placehold.it/32x32",
"age": 26,
"eyeColor": "blue",
"name": "Stout Price",
"gender": "male",
"company": "MENBRAIN",
"email": "stoutprice@menbrain.com",
"phone": "+1 (848) 487-2874",
"address": "819 Linwood Street, Rushford, Wyoming, 8219",
"about": "Irure duis culpa culpa velit excepteur ipsum in cupidatat qui Lorem irure ipsum cillum occaecat. Nisi eiusmod deserunt voluptate quis excepteur nisi cupidatat consectetur mollit irure veniam. Incididunt et do magna laboris dolor in in fugiat duis est in officia mollit irure. Eiusmod magna ut laboris ullamco fugiat ut. Culpa pariatur ut sunt ex pariatur eu incididunt.\r\n",
"registered": "2015-10-21T05:10:06 -01:00",
"latitude": -50.530092,
"longitude": 24.48505,
"tags": [
"adipisicing",
"aute",
"consectetur",
"dolor",
"cillum",
"incididunt",
"dolor"
],
"friends": [
{
"id": 0,
"name": "Garcia Frazier"
},
{
"id": 1,
"name": "Jacobson Ferrell"
},
{
"id": 2,
"name": "Letha Nash"
}
],
"greeting": "Hello, Stout Price! You have 4 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e00a388b6d31f19f77",
"index": 6,
"guid": "8af1cb16-45f6-474a-b066-dd729692280e",
"isActive": true,
"balance": "$3,355.91",
"picture": "http://placehold.it/32x32",
"age": 40,
"eyeColor": "blue",
"name": "Huff Gay",
"gender": "male",
"company": "BIFLEX",
"email": "huffgay@biflex.com",
"phone": "+1 (945) 598-3578",
"address": "990 Livonia Avenue, Deltaville, Federated States Of Micronesia, 7229",
"about": "Velit cillum aliqua minim sit dolor dolore anim. Sunt duis pariatur aliqua eu. Qui ut excepteur et quis proident labore sunt. Occaecat duis duis ipsum dolor eiusmod voluptate excepteur et do eu. Deserunt aute reprehenderit deserunt aliquip cupidatat est deserunt fugiat.\r\n",
"registered": "2014-12-20T08:11:51 -00:00",
"latitude": 71.555629,
"longitude": -12.398118,
"tags": [
"excepteur",
"proident",
"est",
"consequat",
"et",
"anim",
"deserunt"
],
"friends": [
{
"id": 0,
"name": "Maribel Morrison"
},
{
"id": 1,
"name": "Horton Lucas"
},
{
"id": 2,
"name": "Dyer Owens"
}
],
"greeting": "Hello, Huff Gay! You have 1 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e00dffcf1602631a35",
"index": 7,
"guid": "973f2f6e-1591-4a30-b95a-7bdab5b8ee4f",
"isActive": true,
"balance": "$3,550.97",
"picture": "http://placehold.it/32x32",
"age": 35,
"eyeColor": "green",
"name": "Todd Lowe",
"gender": "male",
"company": "STELAECOR",
"email": "toddlowe@stelaecor.com",
"phone": "+1 (930) 511-3317",
"address": "325 Vandalia Avenue, Biehle, Alaska, 8894",
"about": "Non in id ut occaecat aliqua quis eiusmod aute ex ex occaecat cillum tempor. Et veniam pariatur magna id aliquip veniam minim et. Pariatur aliqua ea nisi ut exercitation culpa reprehenderit ea amet ad fugiat. Do duis culpa Lorem pariatur consectetur laboris ea magna. Magna est tempor eu incididunt eiusmod esse est. Consequat magna duis adipisicing ullamco ex in duis excepteur.\r\n",
"registered": "2015-01-06T10:01:17 -00:00",
"latitude": -58.68543,
"longitude": -83.373668,
"tags": [
"incididunt",
"sunt",
"enim",
"nulla",
"qui",
"laborum",
"et"
],
"friends": [
{
"id": 0,
"name": "Delia Bell"
},
{
"id": 1,
"name": "Fisher Joseph"
},
{
"id": 2,
"name": "Solomon William"
}
],
"greeting": "Hello, Todd Lowe! You have 2 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0dbe738a8d36948cf",
"index": 8,
"guid": "3f0226b6-820e-4f58-bb44-89fd30f8b948",
"isActive": false,
"balance": "$1,413.48",
"picture": "http://placehold.it/32x32",
"age": 27,
"eyeColor": "blue",
"name": "Odonnell Brown",
"gender": "male",
"company": "CAPSCREEN",
"email": "odonnellbrown@capscreen.com",
"phone": "+1 (885) 421-2488",
"address": "105 Benson Avenue, Falmouth, Louisiana, 5293",
"about": "Consectetur laboris laborum officia non qui nulla commodo eiusmod. Voluptate et irure ut tempor elit reprehenderit aliqua sunt. Sit dolore pariatur magna officia mollit nulla duis et officia consectetur consequat ipsum ad et. Sunt enim culpa duis velit ullamco enim occaecat magna elit. Labore consequat voluptate cillum eiusmod anim deserunt irure sint mollit.\r\n",
"registered": "2015-10-09T08:09:14 -01:00",
"latitude": 46.208899,
"longitude": -54.199065,
"tags": [
"consectetur",
"ipsum",
"aute",
"qui",
"velit",
"officia",
"elit"
],
"friends": [
{
"id": 0,
"name": "Strickland Coleman"
},
{
"id": 1,
"name": "Glass Goodwin"
},
{
"id": 2,
"name": "Sweeney Lewis"
}
],
"greeting": "Hello, Odonnell Brown! You have 1 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0e7b155b660add81a",
"index": 9,
"guid": "8f4c7cf7-5a2c-4836-8b45-29de735f8147",
"isActive": false,
"balance": "$3,841.84",
"picture": "http://placehold.it/32x32",
"age": 36,
"eyeColor": "brown",
"name": "Mari George",
"gender": "female",
"company": "EARGO",
"email": "marigeorge@eargo.com",
"phone": "+1 (853) 555-2713",
"address": "193 Lorraine Street, Slovan, Nevada, 8317",
"about": "Quis sit duis ut aute aliquip do excepteur dolor sit. Labore tempor sint commodo ad laborum dolore enim sit. Qui occaecat cillum laboris reprehenderit culpa adipisicing nisi labore reprehenderit occaecat culpa fugiat. Sunt aute ad duis irure fugiat anim irure et velit sunt labore cupidatat nostrud.\r\n",
"registered": "2016-05-14T04:27:33 -01:00",
"latitude": 58.255984,
"longitude": -144.49884,
"tags": [
"nisi",
"consectetur",
"veniam",
"duis",
"dolore",
"incididunt",
"nostrud"
],
"friends": [
{
"id": 0,
"name": "Trujillo Morris"
},
{
"id": 1,
"name": "Marci Peterson"
},
{
"id": 2,
"name": "Lauri Patterson"
}
],
"greeting": "Hello, Mari George! You have 6 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0d21d755f171b9f2e",
"index": 10,
"guid": "df12fa14-56c9-4667-b227-a5b5fa84986b",
"isActive": true,
"balance": "$1,378.85",
"picture": "http://placehold.it/32x32",
"age": 23,
"eyeColor": "blue",
"name": "Maddox Fields",
"gender": "male",
"company": "EXOVENT",
"email": "maddoxfields@exovent.com",
"phone": "+1 (978) 474-2874",
"address": "769 George Street, Tampico, Georgia, 6201",
"about": "Irure cupidatat anim sunt id adipisicing ad deserunt exercitation. Laboris ad excepteur adipisicing proident proident laborum dolor excepteur incididunt dolore esse. Et fugiat consectetur est sunt dolor. Fugiat laborum eiusmod officia veniam magna proident sit id Lorem. Eu pariatur esse nulla aliqua.\r\n",
"registered": "2014-02-13T10:35:16 -00:00",
"latitude": -42.589988,
"longitude": 134.198828,
"tags": [
"dolor",
"do",
"amet",
"est",
"in",
"occaecat",
"id"
],
"friends": [
{
"id": 0,
"name": "Alma Jimenez"
},
{
"id": 1,
"name": "Townsend Carson"
},
{
"id": 2,
"name": "Rosalie Koch"
}
],
"greeting": "Hello, Maddox Fields! You have 9 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0a00445667bc655b3",
"index": 11,
"guid": "12dbbedb-bdeb-416a-bbdf-644f1b94a3cc",
"isActive": true,
"balance": "$2,238.77",
"picture": "http://placehold.it/32x32",
"age": 25,
"eyeColor": "green",
"name": "Maxwell Valentine",
"gender": "male",
"company": "GOKO",
"email": "maxwellvalentine@goko.com",
"phone": "+1 (931) 543-3266",
"address": "162 Revere Place, Ebro, Utah, 1977",
"about": "Ad laborum laboris culpa adipisicing. Nulla Lorem fugiat ut excepteur nulla amet est deserunt deserunt voluptate non quis. Consectetur elit dolore do culpa dolore voluptate nostrud voluptate adipisicing velit consectetur anim.\r\n",
"registered": "2015-08-25T05:42:36 -01:00",
"latitude": 4.19182,
"longitude": -130.997793,
"tags": [
"amet",
"in",
"laboris",
"quis",
"laboris",
"velit",
"incididunt"
],
"friends": [
{
"id": 0,
"name": "Deborah Evans"
},
{
"id": 1,
"name": "Parrish Ramsey"
},
{
"id": 2,
"name": "Mona Peck"
}
],
"greeting": "Hello, Maxwell Valentine! You have 3 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e074c69da60d3cdba2",
"index": 12,
"guid": "3914c876-8b44-4cff-997f-0af6b5421b7d",
"isActive": true,
"balance": "$1,383.25",
"picture": "http://placehold.it/32x32",
"age": 32,
"eyeColor": "brown",
"name": "Mia Horne",
"gender": "female",
"company": "COLLAIRE",
"email": "miahorne@collaire.com",
"phone": "+1 (815) 522-3736",
"address": "414 Schenectady Avenue, Beaverdale, Virginia, 206",
"about": "Ea aliquip pariatur aliquip do in mollit consectetur exercitation cillum tempor eu. Ipsum qui elit consequat et ipsum officia. Dolor mollit esse mollit nulla dolore. Aliquip Lorem laborum ex nulla cillum sit fugiat cillum in in irure dolor mollit esse. Quis proident esse magna nostrud excepteur consectetur fugiat anim adipisicing sit ad. Officia eiusmod mollit Lorem quis dolore reprehenderit excepteur magna eiusmod incididunt est magna fugiat aute.\r\n",
"registered": "2015-07-28T01:01:57 -01:00",
"latitude": -69.344682,
"longitude": 80.663244,
"tags": [
"sit",
"reprehenderit",
"adipisicing",
"fugiat",
"elit",
"tempor",
"cillum"
],
"friends": [
{
"id": 0,
"name": "Cherry Montoya"
},
{
"id": 1,
"name": "Eva Vaughan"
},
{
"id": 2,
"name": "Hannah Frank"
}
],
"greeting": "Hello, Mia Horne! You have 6 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e04c7426217f42b103",
"index": 13,
"guid": "cd6d113a-cd7d-4181-b0bb-7485e9bae8fc",
"isActive": true,
"balance": "$2,227.48",
"picture": "http://placehold.it/32x32",
"age": 31,
"eyeColor": "brown",
"name": "Hendrix Merrill",
"gender": "male",
"company": "NEXGENE",
"email": "hendrixmerrill@nexgene.com",
"phone": "+1 (941) 550-2603",
"address": "885 Chestnut Street, Kipp, Kansas, 1943",
"about": "Laborum culpa occaecat aute deserunt. Duis sunt exercitation consectetur proident consectetur culpa et exercitation nulla nisi voluptate id magna. Fugiat veniam tempor exercitation pariatur quis consequat consequat. Consectetur tempor adipisicing est nulla ad. Elit pariatur velit officia do excepteur labore. Cillum ea dolor laborum aute eu fugiat tempor magna cillum.\r\n",
"registered": "2014-06-05T01:32:53 -01:00",
"latitude": 2.447966,
"longitude": -77.298558,
"tags": [
"eiusmod",
"nisi",
"quis",
"occaecat",
"est",
"laboris",
"adipisicing"
],
"friends": [
{
"id": 0,
"name": "Greta Sheppard"
},
{
"id": 1,
"name": "Murray Green"
},
{
"id": 2,
"name": "Nelda Mosley"
}
],
"greeting": "Hello, Hendrix Merrill! You have 9 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0c11eb4ae89cb8941",
"index": 14,
"guid": "8f55a79d-6659-4788-b1d7-938a4576e8f5",
"isActive": false,
"balance": "$3,991.06",
"picture": "http://placehold.it/32x32",
"age": 24,
"eyeColor": "green",
"name": "Katie French",
"gender": "female",
"company": "ZILODYNE",
"email": "katiefrench@zilodyne.com",
"phone": "+1 (956) 568-3631",
"address": "767 Grant Avenue, Montura, Iowa, 3264",
"about": "Ut quis est irure culpa fugiat quis elit aliqua eu veniam dolore. Ut in consectetur ipsum mollit nulla quis. Aute est eu do culpa cillum et dolor nisi pariatur non laborum excepteur. Sint ex dolore magna ex ex magna excepteur ut ea nulla ea. Commodo voluptate ea ad laboris nisi.\r\n",
"registered": "2015-05-10T05:36:10 -01:00",
"latitude": -5.911388,
"longitude": 58.930652,
"tags": [
"voluptate",
"labore",
"officia",
"in",
"laboris",
"exercitation",
"dolore"
],
"friends": [
{
"id": 0,
"name": "Maxine Anderson"
},
{
"id": 1,
"name": "Church Lancaster"
},
{
"id": 2,
"name": "Moran Bush"
}
],
"greeting": "Hello, Katie French! You have 5 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e01f198581dcb0440b",
"index": 15,
"guid": "21bb0db3-4850-4f61-a99d-3dc6b0a0bd02",
"isActive": false,
"balance": "$3,632.14",
"picture": "http://placehold.it/32x32",
"age": 37,
"eyeColor": "brown",
"name": "Gilliam Steele",
"gender": "male",
"company": "SONIQUE",
"email": "gilliamsteele@sonique.com",
"phone": "+1 (921) 541-3991",
"address": "710 Beadel Street, Cazadero, Michigan, 1823",
"about": "Est fugiat occaecat enim aliquip id reprehenderit eiusmod aute ea minim. Labore amet pariatur laborum consequat ex id voluptate aute. Magna nisi sit minim amet aliquip fugiat amet ad mollit eiusmod cupidatat esse.\r\n",
"registered": "2014-04-15T11:37:21 -01:00",
"latitude": -80.87436,
"longitude": -105.724668,
"tags": [
"ipsum",
"esse",
"laboris",
"ut",
"aute",
"consequat",
"culpa"
],
"friends": [
{
"id": 0,
"name": "Ford Warner"
},
{
"id": 1,
"name": "Talley Collins"
},
{
"id": 2,
"name": "Ruiz Witt"
}
],
"greeting": "Hello, Gilliam Steele! You have 8 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e02cafd193b45f9464",
"index": 16,
"guid": "8208b859-3fda-4450-bb27-246159fe6243",
"isActive": true,
"balance": "$2,105.73",
"picture": "http://placehold.it/32x32",
"age": 39,
"eyeColor": "green",
"name": "Mamie Riddle",
"gender": "female",
"company": "ZENCO",
"email": "mamieriddle@zenco.com",
"phone": "+1 (829) 530-3147",
"address": "425 Ide Court, Moquino, South Dakota, 496",
"about": "Ut eu ex ut minim Lorem anim non. Ullamco occaecat ad cupidatat nostrud duis cillum duis sit qui anim anim do. Adipisicing aliquip ut mollit elit laborum esse aute ex culpa fugiat veniam nostrud adipisicing.\r\n",
"registered": "2014-07-07T03:36:39 -01:00",
"latitude": 67.441591,
"longitude": -140.673288,
"tags": [
"magna",
"sint",
"incididunt",
"ullamco",
"ad",
"Lorem",
"sit"
],
"friends": [
{
"id": 0,
"name": "Tasha Santiago"
},
{
"id": 1,
"name": "Franks Trujillo"
},
{
"id": 2,
"name": "Fulton Stanley"
}
],
"greeting": "Hello, Mamie Riddle! You have 2 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e076b0c224aa2909c3",
"index": 17,
"guid": "66efc2e3-5139-4798-8047-08f0e6c699dc",
"isActive": true,
"balance": "$2,717.34",
"picture": "http://placehold.it/32x32",
"age": 34,
"eyeColor": "brown",
"name": "Randall Mckee",
"gender": "male",
"company": "ZOLAREX",
"email": "randallmckee@zolarex.com",
"phone": "+1 (844) 480-2796",
"address": "408 Nichols Avenue, Olney, Colorado, 2011",
"about": "Proident commodo laborum officia ullamco sit. Eu magna quis incididunt occaecat anim exercitation pariatur velit ut ea ex et exercitation. Pariatur nisi enim elit aute duis veniam sunt ex aute nostrud adipisicing. Consequat quis laboris proident sit esse culpa fugiat quis ad quis laborum. Qui eiusmod qui consectetur elit deserunt mollit enim qui esse et pariatur ex. Nostrud dolore amet irure id velit velit. Exercitation sint magna proident deserunt nulla reprehenderit eu exercitation laboris veniam.\r\n",
"registered": "2016-03-23T02:40:14 -00:00",
"latitude": 37.145673,
"longitude": 105.136539,
"tags": [
"deserunt",
"in",
"nulla",
"incididunt",
"sunt",
"non",
"sit"
],
"friends": [
{
"id": 0,
"name": "Henson Oneil"
},
{
"id": 1,
"name": "Ida Beach"
},
{
"id": 2,
"name": "Velma Boyd"
}
],
"greeting": "Hello, Randall Mckee! You have 8 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e06b53aa778aa454d0",
"index": 18,
"guid": "97fb4f12-e8b9-4dd9-a67f-7f2cd35eca98",
"isActive": false,
"balance": "$2,659.19",
"picture": "http://placehold.it/32x32",
"age": 39,
"eyeColor": "blue",
"name": "Dolly Robinson",
"gender": "female",
"company": "ZENSOR",
"email": "dollyrobinson@zensor.com",
"phone": "+1 (825) 481-3281",
"address": "527 Joval Court, Rew, Oregon, 4868",
"about": "Elit cupidatat officia velit laborum cupidatat reprehenderit officia sunt occaecat ea quis elit. Nostrud ad consectetur officia aute in ullamco enim cillum minim veniam. Mollit aliquip sit est exercitation labore enim qui anim deserunt dolore esse non cupidatat. Lorem ex ea nulla sunt ullamco. Fugiat mollit minim nostrud laboris labore reprehenderit ex cupidatat exercitation ea officia deserunt aliquip tempor. Enim quis occaecat sint id dolor eu et et non velit fugiat Lorem. Ea anim reprehenderit deserunt in occaecat ea Lorem.\r\n",
"registered": "2015-03-22T12:05:04 -00:00",
"latitude": -22.241832,
"longitude": 29.141163,
"tags": [
"sint",
"reprehenderit",
"do",
"nisi",
"qui",
"magna",
"pariatur"
],
"friends": [
{
"id": 0,
"name": "Mcdowell Sanchez"
},
{
"id": 1,
"name": "Valentine Ware"
},
{
"id": 2,
"name": "Sharpe York"
}
],
"greeting": "Hello, Dolly Robinson! You have 3 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0aca4e42178a4d01d",
"index": 19,
"guid": "c3fece3c-0064-4e0d-81cf-051a1975798e",
"isActive": true,
"balance": "$2,084.58",
"picture": "http://placehold.it/32x32",
"age": 37,
"eyeColor": "green",
"name": "Reilly Allen",
"gender": "male",
"company": "BITREX",
"email": "reillyallen@bitrex.com",
"phone": "+1 (921) 467-2956",
"address": "390 Jackson Court, Weeksville, Wisconsin, 2490",
"about": "Deserunt irure proident anim veniam cupidatat fugiat irure labore duis. Cupidatat ullamco ullamco minim eu nisi et est ut laborum commodo fugiat proident tempor. Magna consequat sit irure eiusmod sunt ullamco ea magna non anim consequat. Qui enim enim minim nisi ipsum minim ut. Id esse tempor dolor labore dolore excepteur.\r\n",
"registered": "2016-02-05T05:35:25 -00:00",
"latitude": -14.966696,
"longitude": 133.802008,
"tags": [
"magna",
"aute",
"sunt",
"sunt",
"mollit",
"nulla",
"eiusmod"
],
"friends": [
{
"id": 0,
"name": "Dolores Mcclain"
},
{
"id": 1,
"name": "Burris Kennedy"
},
{
"id": 2,
"name": "Miranda Levine"
}
],
"greeting": "Hello, Reilly Allen! You have 1 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e039a41f280dc5d74c",
"index": 20,
"guid": "cfaca1bc-b5f2-4c9d-947d-1f6f3dd4ae17",
"isActive": true,
"balance": "$2,380.76",
"picture": "http://placehold.it/32x32",
"age": 31,
"eyeColor": "brown",
"name": "Josefa Drake",
"gender": "female",
"company": "MUSAPHICS",
"email": "josefadrake@musaphics.com",
"phone": "+1 (833) 425-3968",
"address": "763 Chester Avenue, Wiscon, Vermont, 8414",
"about": "Nisi incididunt eiusmod exercitation aute amet elit consectetur irure consequat minim aute. Et duis enim nostrud aliqua ex duis et magna mollit mollit irure eu nostrud. Proident eu proident sint qui officia velit. Veniam officia commodo esse occaecat ea nisi duis ex labore enim do.\r\n",
"registered": "2016-06-16T02:38:15 -01:00",
"latitude": -26.803409,
"longitude": -7.197203,
"tags": [
"irure",
"reprehenderit",
"cupidatat",
"mollit",
"ad",
"pariatur",
"ipsum"
],
"friends": [
{
"id": 0,
"name": "Rodgers Padilla"
},
{
"id": 1,
"name": "Hale Kinney"
},
{
"id": 2,
"name": "Bertie Randall"
}
],
"greeting": "Hello, Josefa Drake! You have 3 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e099393074687a3474",
"index": 21,
"guid": "7132d430-8316-4046-8959-a6b469d1b21b",
"isActive": true,
"balance": "$2,169.93",
"picture": "http://placehold.it/32x32",
"age": 24,
"eyeColor": "green",
"name": "Marissa Randolph",
"gender": "female",
"company": "EYERIS",
"email": "marissarandolph@eyeris.com",
"phone": "+1 (829) 464-3886",
"address": "714 Elliott Place, Harleigh, American Samoa, 4027",
"about": "Occaecat veniam duis officia irure. Culpa in mollit anim incididunt tempor incididunt proident ea tempor incididunt qui. Ea consequat eu est enim cupidatat cupidatat qui exercitation commodo. Aliqua sit veniam eiusmod aliqua eiusmod. Reprehenderit eu aute ex dolor est labore sunt. Sunt id do non irure elit reprehenderit elit esse irure velit enim cupidatat culpa.\r\n",
"registered": "2014-04-04T05:17:26 -01:00",
"latitude": -62.188117,
"longitude": -27.382353,
"tags": [
"esse",
"cillum",
"esse",
"id",
"est",
"voluptate",
"enim"
],
"friends": [
{
"id": 0,
"name": "Olsen Montgomery"
},
{
"id": 1,
"name": "Jordan Spencer"
},
{
"id": 2,
"name": "Angelina Mason"
}
],
"greeting": "Hello, Marissa Randolph! You have 9 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e00b00187856495637",
"index": 22,
"guid": "81aa75a9-16b9-4963-b2b0-25e89cfda9c9",
"isActive": false,
"balance": "$3,917.68",
"picture": "http://placehold.it/32x32",
"age": 33,
"eyeColor": "brown",
"name": "Pansy Schroeder",
"gender": "female",
"company": "BUZZOPIA",
"email": "pansyschroeder@buzzopia.com",
"phone": "+1 (995) 594-3242",
"address": "674 Seigel Street, Bend, Delaware, 8333",
"about": "Aliquip fugiat excepteur cupidatat ullamco do amet proident. Pariatur tempor cupidatat anim voluptate cillum sint do aliquip aliqua commodo dolor aute. Nisi officia eiusmod enim magna irure amet sit voluptate sint eiusmod reprehenderit in. Lorem excepteur ad aliqua mollit. Elit ex eiusmod nisi incididunt.\r\n",
"registered": "2016-04-14T02:15:57 -01:00",
"latitude": 18.165001,
"longitude": -104.077673,
"tags": [
"proident",
"est",
"consequat",
"et",
"et",
"eu",
"sunt"
],
"friends": [
{
"id": 0,
"name": "Eugenia Bowman"
},
{
"id": 1,
"name": "Ursula Henderson"
},
{
"id": 2,
"name": "Audra Larson"
}
],
"greeting": "Hello, Pansy Schroeder! You have 7 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0ec55fba6ccd4ef90",
"index": 23,
"guid": "2fa47874-9010-4046-8efc-c23c567cd6c8",
"isActive": true,
"balance": "$2,710.01",
"picture": "http://placehold.it/32x32",
"age": 33,
"eyeColor": "brown",
"name": "Diane Hansen",
"gender": "female",
"company": "OLUCORE",
"email": "dianehansen@olucore.com",
"phone": "+1 (902) 404-3201",
"address": "674 Story Court, Osmond, Oklahoma, 1169",
"about": "Officia reprehenderit sunt ex nostrud. Commodo ut veniam et ullamco dolor cupidatat occaecat amet laborum ut nostrud voluptate id. Magna mollit officia ipsum elit proident enim. Cupidatat ipsum culpa cupidatat est ullamco mollit. Mollit sint veniam officia ea proident. Magna labore id veniam sint duis fugiat laborum nostrud dolore reprehenderit quis esse.\r\n",
"registered": "2015-09-29T05:32:38 -01:00",
"latitude": 73.335514,
"longitude": -168.254296,
"tags": [
"est",
"non",
"labore",
"do",
"ipsum",
"consectetur",
"cillum"
],
"friends": [
{
"id": 0,
"name": "Aisha Bird"
},
{
"id": 1,
"name": "Kirk Mclaughlin"
},
{
"id": 2,
"name": "Adeline Pickett"
}
],
"greeting": "Hello, Diane Hansen! You have 4 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0e41b1268dafaa356",
"index": 24,
"guid": "008de1b3-8f82-431e-9d1a-769c1472bc7d",
"isActive": true,
"balance": "$2,945.80",
"picture": "http://placehold.it/32x32",
"age": 27,
"eyeColor": "green",
"name": "Woodward Wade",
"gender": "male",
"company": "UNDERTAP",
"email": "woodwardwade@undertap.com",
"phone": "+1 (865) 469-3949",
"address": "922 Temple Court, Nash, New Mexico, 4674",
"about": "Est velit incididunt sit sunt nostrud laborum ut occaecat eu occaecat irure nisi sit eiusmod. Eiusmod magna dolore sint reprehenderit aute. Incididunt id nisi tempor cupidatat qui enim sit id aliqua est fugiat adipisicing. Fugiat commodo duis eiusmod eu duis. Id adipisicing ipsum ex pariatur ipsum quis non duis nulla occaecat voluptate. Lorem culpa exercitation nostrud dolore elit tempor. Tempor nisi in duis laborum.\r\n",
"registered": "2014-12-01T01:04:04 -00:00",
"latitude": 77.951447,
"longitude": -37.781887,
"tags": [
"do",
"mollit",
"mollit",
"est",
"id",
"ullamco",
"proident"
],
"friends": [
{
"id": 0,
"name": "Lara Conrad"
},
{
"id": 1,
"name": "Fern Watts"
},
{
"id": 2,
"name": "Perry Potts"
}
],
"greeting": "Hello, Woodward Wade! You have 1 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0a22e651be5289c6e",
"index": 25,
"guid": "2333e6ea-43c2-4993-8f95-c60683bc04a6",
"isActive": true,
"balance": "$1,314.69",
"picture": "http://placehold.it/32x32",
"age": 23,
"eyeColor": "green",
"name": "Grimes Greene",
"gender": "male",
"company": "BRAINQUIL",
"email": "grimesgreene@brainquil.com",
"phone": "+1 (976) 469-2740",
"address": "613 Pulaski Street, Goochland, Texas, 3857",
"about": "Quis ex in consequat nulla quis esse laboris ullamco cillum occaecat velit nulla. Laboris quis fugiat cillum mollit tempor sit ipsum consectetur nostrud et. Velit voluptate nulla cillum esse aliqua aute sunt veniam amet in aliquip culpa quis. Culpa officia laboris anim amet veniam non in labore fugiat consectetur dolore dolor sit occaecat. Aliquip do enim enim pariatur sit. Fugiat laborum velit occaecat pariatur amet. Culpa eiusmod aliquip labore consequat culpa enim pariatur proident magna labore.\r\n",
"registered": "2014-08-05T12:09:49 -01:00",
"latitude": -67.859063,
"longitude": -105.362914,
"tags": [
"commodo",
"aliquip",
"id",
"consectetur",
"commodo",
"ipsum",
"commodo"
],
"friends": [
{
"id": 0,
"name": "Lakeisha Oneal"
},
{
"id": 1,
"name": "Christy Lloyd"
},
{
"id": 2,
"name": "Allen Tillman"
}
],
"greeting": "Hello, Grimes Greene! You have 3 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e007d49b429fb32406",
"index": 26,
"guid": "5ef9f022-50e1-4d4d-9d63-95a0097558f2",
"isActive": true,
"balance": "$2,025.49",
"picture": "http://placehold.it/32x32",
"age": 32,
"eyeColor": "green",
"name": "Edith Hubbard",
"gender": "female",
"company": "ROBOID",
"email": "edithhubbard@roboid.com",
"phone": "+1 (919) 424-3545",
"address": "888 Havens Place, Bonanza, Washington, 3189",
"about": "Pariatur ad reprehenderit consectetur fugiat deserunt cupidatat culpa dolor officia eiusmod pariatur enim dolore veniam. Ullamco ipsum magna eu et occaecat velit duis consectetur cupidatat aute. Sit ut cillum proident magna qui anim laborum laboris tempor amet adipisicing anim. Ex consequat velit commodo magna aliqua aliqua in magna. Pariatur Lorem ullamco veniam ipsum pariatur duis nulla nulla occaecat sint reprehenderit. Proident elit nostrud exercitation ipsum Lorem fugiat sunt do nostrud.\r\n",
"registered": "2015-10-21T07:50:46 -01:00",
"latitude": 81.568315,
"longitude": -18.910748,
"tags": [
"voluptate",
"consectetur",
"non",
"in",
"excepteur",
"ipsum",
"et"
],
"friends": [
{
"id": 0,
"name": "Janell Rojas"
},
{
"id": 1,
"name": "Barrett Alvarez"
},
{
"id": 2,
"name": "Lindsey Summers"
}
],
"greeting": "Hello, Edith Hubbard! You have 9 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0ab868d8f75166280",
"index": 27,
"guid": "1456aa18-206b-45e3-8a3a-62814b04a791",
"isActive": true,
"balance": "$2,104.36",
"picture": "http://placehold.it/32x32",
"age": 23,
"eyeColor": "blue",
"name": "Sanford Skinner",
"gender": "male",
"company": "ANARCO",
"email": "sanfordskinner@anarco.com",
"phone": "+1 (804) 557-3353",
"address": "683 Morgan Avenue, Ernstville, Arkansas, 4330",
"about": "Veniam cillum minim anim minim aliqua occaecat amet id elit est exercitation dolor. Lorem in velit incididunt laborum. Duis incididunt cillum dolor deserunt eu sunt pariatur aute.\r\n",
"registered": "2014-01-21T12:21:54 -00:00",
"latitude": -16.471178,
"longitude": 171.440045,
"tags": [
"consequat",
"aliqua",
"quis",
"proident",
"Lorem",
"anim",
"aliqua"
],
"friends": [
{
"id": 0,
"name": "Hope Compton"
},
{
"id": 1,
"name": "Marta Shaffer"
},
{
"id": 2,
"name": "Josephine Nguyen"
}
],
"greeting": "Hello, Sanford Skinner! You have 6 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e08a0599e252b1cfc5",
"index": 28,
"guid": "70877401-7d7d-4007-914a-0e0635b7978e",
"isActive": false,
"balance": "$1,378.31",
"picture": "http://placehold.it/32x32",
"age": 29,
"eyeColor": "brown",
"name": "Olivia Vasquez",
"gender": "female",
"company": "GEEKOLOGY",
"email": "oliviavasquez@geekology.com",
"phone": "+1 (999) 506-3910",
"address": "911 Foster Avenue, Clarence, Virgin Islands, 3296",
"about": "Dolor sunt laborum laboris aliqua deserunt minim aute mollit pariatur reprehenderit aliquip duis dolore esse. Est Lorem cillum sunt aute aute. Laboris adipisicing tempor consequat incididunt amet Lorem commodo. Amet id dolor eiusmod veniam dolore aliqua qui esse elit enim aliquip reprehenderit laboris. Anim aliqua ad duis dolore voluptate minim. Eiusmod incididunt excepteur sint officia eu.\r\n",
"registered": "2016-05-06T01:10:12 -01:00",
"latitude": -50.046379,
"longitude": -19.533607,
"tags": [
"sint",
"ad",
"amet",
"nisi",
"culpa",
"ex",
"magna"
],
"friends": [
{
"id": 0,
"name": "Buchanan Frederick"
},
{
"id": 1,
"name": "Goodwin Webb"
},
{
"id": 2,
"name": "Noelle Hensley"
}
],
"greeting": "Hello, Olivia Vasquez! You have 5 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e03b22aa6a2915be0c",
"index": 29,
"guid": "e8bd6b80-e3c7-4b5d-b386-c8a303467474",
"isActive": true,
"balance": "$2,504.46",
"picture": "http://placehold.it/32x32",
"age": 20,
"eyeColor": "brown",
"name": "Mayo Odom",
"gender": "male",
"company": "SLOFAST",
"email": "mayoodom@slofast.com",
"phone": "+1 (946) 525-2708",
"address": "818 Charles Place, Dennard, Alabama, 7824",
"about": "Elit esse tempor laborum deserunt labore tempor. Consectetur nisi irure eu est qui ullamco veniam mollit fugiat mollit laboris cupidatat. Do ipsum sit laboris deserunt aliqua deserunt laboris eu adipisicing duis voluptate minim. Aliquip amet consequat consequat pariatur laborum aute ad. Ea consectetur sunt aliqua eiusmod eu sit dolore. Aute occaecat voluptate reprehenderit cillum ea. Elit amet nulla aute ullamco aliqua incididunt cupidatat.\r\n",
"registered": "2014-12-07T06:37:22 -00:00",
"latitude": 40.830701,
"longitude": 96.899559,
"tags": [
"sit",
"in",
"incididunt",
"elit",
"voluptate",
"in",
"consequat"
],
"friends": [
{
"id": 0,
"name": "Tyson Allison"
},
{
"id": 1,
"name": "Chasity Christian"
},
{
"id": 2,
"name": "Janet Franklin"
}
],
"greeting": "Hello, Mayo Odom! You have 6 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e080c05c1a1037168c",
"index": 30,
"guid": "4728ac5a-fa59-4051-991e-8675f0d5630d",
"isActive": true,
"balance": "$2,040.79",
"picture": "http://placehold.it/32x32",
"age": 31,
"eyeColor": "green",
"name": "May Petty",
"gender": "male",
"company": "FURNAFIX",
"email": "maypetty@furnafix.com",
"phone": "+1 (923) 444-2426",
"address": "640 Kent Avenue, Avalon, Maine, 6401",
"about": "Adipisicing aliquip tempor sint exercitation veniam esse aute consectetur mollit veniam. Do ullamco qui nostrud ut mollit. Ex consequat ullamco consequat laborum enim et. Laborum sunt deserunt nisi est tempor.\r\n",
"registered": "2016-01-07T09:22:48 -00:00",
"latitude": 4.008396,
"longitude": 97.166004,
"tags": [
"ipsum",
"occaecat",
"nisi",
"magna",
"cillum",
"fugiat",
"cillum"
],
"friends": [
{
"id": 0,
"name": "Hyde Lindsey"
},
{
"id": 1,
"name": "Morrison Whitaker"
},
{
"id": 2,
"name": "Josefina Mejia"
}
],
"greeting": "Hello, May Petty! You have 7 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e06b0e710ab84333c7",
"index": 31,
"guid": "4c60bf44-7a9c-454e-b790-18a76d3b6225",
"isActive": false,
"balance": "$3,593.87",
"picture": "http://placehold.it/32x32",
"age": 25,
"eyeColor": "blue",
"name": "Gomez Bradford",
"gender": "male",
"company": "PHARMEX",
"email": "gomezbradford@pharmex.com",
"phone": "+1 (924) 438-3488",
"address": "278 Bancroft Place, Laurelton, Arizona, 2391",
"about": "Amet deserunt exercitation voluptate ea aliqua anim minim non. Velit nostrud culpa laborum eu reprehenderit est ex eu eu aliqua proident culpa. Eu dolore adipisicing tempor proident veniam mollit consequat magna elit magna velit. Ipsum minim culpa esse ut amet laborum sint minim nisi reprehenderit dolore sit in deserunt. Veniam sint deserunt dolor labore et est non consequat et. Minim qui pariatur sit irure magna irure sint.\r\n",
"registered": "2016-07-14T08:49:45 -01:00",
"latitude": 16.357279,
"longitude": -7.912835,
"tags": [
"voluptate",
"in",
"culpa",
"excepteur",
"aliquip",
"mollit",
"culpa"
],
"friends": [
{
"id": 0,
"name": "Brandie Winters"
},
{
"id": 1,
"name": "Myra Simon"
},
{
"id": 2,
"name": "Willie Gonzalez"
}
],
"greeting": "Hello, Gomez Bradford! You have 9 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e01d05944944656a44",
"index": 32,
"guid": "2dcd6271-2581-44e7-a5ee-1c17c9fa01ff",
"isActive": true,
"balance": "$1,063.85",
"picture": "http://placehold.it/32x32",
"age": 31,
"eyeColor": "brown",
"name": "Kinney Berg",
"gender": "male",
"company": "TWIGGERY",
"email": "kinneyberg@twiggery.com",
"phone": "+1 (968) 599-2532",
"address": "613 Livingston Street, Como, North Dakota, 8606",
"about": "Anim in adipisicing amet eiusmod aute pariatur nulla dolor qui nisi et amet dolor. Voluptate Lorem quis in laboris. Excepteur ad aliquip dolore sunt adipisicing aliquip id esse labore ad duis. Cillum veniam consectetur sit ea aliqua duis laboris sint laborum commodo. Occaecat elit quis in aliquip reprehenderit ipsum nostrud minim dolore eu commodo amet velit eiusmod. Consectetur ipsum commodo aute cupidatat deserunt commodo deserunt nulla est ut aliqua. Esse culpa consequat dolor ad ipsum incididunt laboris dolor irure velit.\r\n",
"registered": "2015-08-17T09:00:38 -01:00",
"latitude": 52.236018,
"longitude": -112.096253,
"tags": [
"culpa",
"eiusmod",
"enim",
"irure",
"sit",
"eiusmod",
"exercitation"
],
"friends": [
{
"id": 0,
"name": "Gordon Vincent"
},
{
"id": 1,
"name": "Kidd Morales"
},
{
"id": 2,
"name": "Fletcher Bullock"
}
],
"greeting": "Hello, Kinney Berg! You have 6 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0fd668b97141dd0f2",
"index": 33,
"guid": "d2386ac4-bb9d-41cc-a292-27091a3f0d0f",
"isActive": true,
"balance": "$2,317.70",
"picture": "http://placehold.it/32x32",
"age": 31,
"eyeColor": "green",
"name": "Valeria Henson",
"gender": "female",
"company": "AQUAZURE",
"email": "valeriahenson@aquazure.com",
"phone": "+1 (910) 504-3833",
"address": "185 Beverly Road, Delshire, South Carolina, 4454",
"about": "Ex ullamco id reprehenderit do. Aliquip magna tempor sint quis amet cillum nostrud nulla nulla enim excepteur. Qui dolore amet esse velit dolore ad id proident esse labore.\r\n",
"registered": "2014-06-02T11:13:44 -01:00",
"latitude": -39.67372,
"longitude": 149.724847,
"tags": [
"consectetur",
"exercitation",
"culpa",
"amet",
"dolore",
"sit",
"eiusmod"
],
"friends": [
{
"id": 0,
"name": "Ester Ballard"
},
{
"id": 1,
"name": "Marisa Woodard"
},
{
"id": 2,
"name": "Pena White"
}
],
"greeting": "Hello, Valeria Henson! You have 8 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e09ad3b2a17c9f1629",
"index": 34,
"guid": "c212a7bd-bce6-4b98-b6da-90ef31add513",
"isActive": false,
"balance": "$3,062.79",
"picture": "http://placehold.it/32x32",
"age": 37,
"eyeColor": "brown",
"name": "Dianna Hughes",
"gender": "female",
"company": "SYNTAC",
"email": "diannahughes@syntac.com",
"phone": "+1 (914) 555-2435",
"address": "677 Railroad Avenue, Gouglersville, Puerto Rico, 3708",
"about": "Officia consectetur velit ea fugiat veniam eu. In dolore non ut minim veniam Lorem eiusmod aliquip ullamco. Laborum officia aute do ullamco voluptate. Nostrud ullamco velit consequat enim ex deserunt consectetur id et occaecat dolor fugiat officia id. Et velit non commodo consequat sunt eu.\r\n",
"registered": "2014-07-15T10:59:20 -01:00",
"latitude": -41.993858,
"longitude": 116.314905,
"tags": [
"sunt",
"quis",
"aute",
"cillum",
"cupidatat",
"nostrud",
"nostrud"
],
"friends": [
{
"id": 0,
"name": "Serena Gill"
},
{
"id": 1,
"name": "Kirsten Sanders"
},
{
"id": 2,
"name": "Allyson Maynard"
}
],
"greeting": "Hello, Dianna Hughes! You have 3 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e04c70572ece78d9f2",
"index": 35,
"guid": "282c0170-0ed4-4fad-9ef8-3ba98ceab099",
"isActive": true,
"balance": "$2,034.59",
"picture": "http://placehold.it/32x32",
"age": 27,
"eyeColor": "green",
"name": "Brianna Flores",
"gender": "female",
"company": "BYTREX",
"email": "briannaflores@bytrex.com",
"phone": "+1 (822) 515-3845",
"address": "537 Chapel Street, Darlington, Maryland, 928",
"about": "Magna consectetur consectetur ullamco dolor. Ut ipsum ullamco aliqua duis ad sit est. Amet fugiat labore commodo commodo non ullamco labore enim occaecat anim commodo dolore ullamco mollit. Velit ex labore excepteur irure eu commodo laboris quis.\r\n",
"registered": "2016-01-27T07:11:11 -00:00",
"latitude": -52.606611,
"longitude": -78.129966,
"tags": [
"officia",
"ullamco",
"ut",
"do",
"laboris",
"laborum",
"nisi"
],
"friends": [
{
"id": 0,
"name": "Stacey Fuller"
},
{
"id": 1,
"name": "Dean Mays"
},
{
"id": 2,
"name": "Oneill Fowler"
}
],
"greeting": "Hello, Brianna Flores! You have 2 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e00f242db655dd378c",
"index": 36,
"guid": "f352c627-0724-4104-8c08-38d072577e22",
"isActive": false,
"balance": "$3,106.54",
"picture": "http://placehold.it/32x32",
"age": 22,
"eyeColor": "blue",
"name": "Burke Lawrence",
"gender": "male",
"company": "RONELON",
"email": "burkelawrence@ronelon.com",
"phone": "+1 (982) 557-2568",
"address": "636 Lincoln Place, Williams, California, 7695",
"about": "Sint officia exercitation labore irure id mollit duis nulla dolore anim ullamco. Excepteur enim consequat duis et reprehenderit dolore tempor tempor voluptate cillum elit. Qui eu nulla et commodo aute ut minim veniam esse consectetur duis elit. Reprehenderit occaecat aliquip duis magna ex laborum est laboris dolore.\r\n",
"registered": "2016-05-27T07:38:38 -01:00",
"latitude": -84.811775,
"longitude": -164.259892,
"tags": [
"irure",
"commodo",
"minim",
"deserunt",
"laborum",
"dolor",
"tempor"
],
"friends": [
{
"id": 0,
"name": "Lydia Molina"
},
{
"id": 1,
"name": "Mindy Aguilar"
},
{
"id": 2,
"name": "Alyssa Cardenas"
}
],
"greeting": "Hello, Burke Lawrence! You have 9 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0e19be610ae5c43b6",
"index": 37,
"guid": "6d2f0fc4-9ff5-4647-a653-87451b649a9c",
"isActive": false,
"balance": "$1,512.76",
"picture": "http://placehold.it/32x32",
"age": 23,
"eyeColor": "blue",
"name": "Carmella Hopkins",
"gender": "female",
"company": "APEX",
"email": "carmellahopkins@apex.com",
"phone": "+1 (803) 417-3989",
"address": "995 Harbor Court, Faywood, Connecticut, 1211",
"about": "Proident sunt elit in labore nulla do. Exercitation ea nisi non ex velit amet enim. Officia ullamco duis ad aute duis irure et sunt qui ad ad anim aliqua magna. Lorem consectetur sint elit commodo velit anim.\r\n",
"registered": "2015-11-04T05:00:11 -00:00",
"latitude": 77.56153,
"longitude": 124.186986,
"tags": [
"non",
"proident",
"anim",
"fugiat",
"amet",
"id",
"reprehenderit"
],
"friends": [
{
"id": 0,
"name": "Bettye Burgess"
},
{
"id": 1,
"name": "Leanne Mathews"
},
{
"id": 2,
"name": "Jannie Hamilton"
}
],
"greeting": "Hello, Carmella Hopkins! You have 6 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0e13a50c23183452f",
"index": 38,
"guid": "ee72ec20-36cf-4acf-a11d-ee8d19740b09",
"isActive": true,
"balance": "$1,181.62",
"picture": "http://placehold.it/32x32",
"age": 38,
"eyeColor": "brown",
"name": "Camacho Singleton",
"gender": "male",
"company": "NIQUENT",
"email": "camachosingleton@niquent.com",
"phone": "+1 (811) 583-2481",
"address": "824 Aberdeen Street, Jardine, Kentucky, 8047",
"about": "Exercitation laboris veniam adipisicing eiusmod exercitation ea dolor. Consectetur veniam cillum ullamco officia duis nulla est fugiat nisi eu irure magna qui tempor. Consectetur ad exercitation do enim quis in aute Lorem minim tempor occaecat commodo dolor adipisicing. Nulla nulla id sit laboris dolore eiusmod voluptate veniam esse nisi ullamco reprehenderit. Est officia non sunt amet nulla qui eiusmod irure Lorem proident irure esse.\r\n",
"registered": "2015-06-08T04:14:22 -01:00",
"latitude": 2.526978,
"longitude": -114.123626,
"tags": [
"occaecat",
"nisi",
"duis",
"excepteur",
"cupidatat",
"aliquip",
"esse"
],
"friends": [
{
"id": 0,
"name": "Quinn Pacheco"
},
{
"id": 1,
"name": "Jeanette Shepard"
},
{
"id": 2,
"name": "Leticia Moran"
}
],
"greeting": "Hello, Camacho Singleton! You have 6 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e083fd33d447bdf5f0",
"index": 39,
"guid": "88e1ea54-05d6-41b2-aa14-e0a09c3cae52",
"isActive": true,
"balance": "$2,997.75",
"picture": "http://placehold.it/32x32",
"age": 27,
"eyeColor": "green",
"name": "Frank Mendoza",
"gender": "male",
"company": "SURETECH",
"email": "frankmendoza@suretech.com",
"phone": "+1 (886) 461-3359",
"address": "635 Bay Parkway, Waterloo, Minnesota, 8289",
"about": "Irure enim enim quis incididunt. Nostrud ut non nisi sit voluptate commodo. Qui do nulla ex officia labore eu consequat sit quis.\r\n",
"registered": "2016-06-28T06:27:03 -01:00",
"latitude": 2.929115,
"longitude": -168.804307,
"tags": [
"nisi",
"duis",
"ex",
"proident",
"proident",
"cupidatat",
"reprehenderit"
],
"friends": [
{
"id": 0,
"name": "Juarez Clay"
},
{
"id": 1,
"name": "Lilian Joyner"
},
{
"id": 2,
"name": "Vanessa Wong"
}
],
"greeting": "Hello, Frank Mendoza! You have 3 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e056318745ed13c874",
"index": 40,
"guid": "6b3908e0-db5b-4a64-9995-b57f0533b0a0",
"isActive": false,
"balance": "$3,794.73",
"picture": "http://placehold.it/32x32",
"age": 29,
"eyeColor": "green",
"name": "Celina Everett",
"gender": "female",
"company": "GADTRON",
"email": "celinaeverett@gadtron.com",
"phone": "+1 (884) 555-3346",
"address": "992 Havemeyer Street, Crayne, Idaho, 5113",
"about": "Qui occaecat quis nulla duis consequat aliqua qui qui. Exercitation officia reprehenderit proident labore incididunt officia id nisi commodo et. Aliqua ut incididunt in et proident reprehenderit eu consequat do. Id Lorem Lorem eu ad veniam reprehenderit id voluptate mollit deserunt anim.\r\n",
"registered": "2016-09-05T07:38:12 -01:00",
"latitude": 67.407883,
"longitude": -161.007684,
"tags": [
"consequat",
"velit",
"in",
"ea",
"et",
"id",
"occaecat"
],
"friends": [
{
"id": 0,
"name": "Gabriela Waters"
},
{
"id": 1,
"name": "Charity Daniels"
},
{
"id": 2,
"name": "Osborn Todd"
}
],
"greeting": "Hello, Celina Everett! You have 4 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0f034002a5909ba81",
"index": 41,
"guid": "860aba0c-3451-447f-87f4-a28b83ac1568",
"isActive": true,
"balance": "$3,675.07",
"picture": "http://placehold.it/32x32",
"age": 30,
"eyeColor": "green",
"name": "Taylor Gonzales",
"gender": "female",
"company": "DOGNOSIS",
"email": "taylorgonzales@dognosis.com",
"phone": "+1 (802) 475-3558",
"address": "567 Congress Street, Hackneyville, Ohio, 8040",
"about": "Pariatur duis id nulla ut occaecat ea proident est id est et. Anim anim in elit ullamco laborum enim duis dolor duis. Deserunt sint amet sint cupidatat qui. Ad est fugiat consequat esse dolore amet ex ea officia eu ex dolore consequat.\r\n",
"registered": "2014-02-11T12:43:07 -00:00",
"latitude": -82.718658,
"longitude": -170.968249,
"tags": [
"eiusmod",
"commodo",
"eu",
"elit",
"aliquip",
"ullamco",
"minim"
],
"friends": [
{
"id": 0,
"name": "Aguirre Wilson"
},
{
"id": 1,
"name": "Jana Wiggins"
},
{
"id": 2,
"name": "Sonja Bond"
}
],
"greeting": "Hello, Taylor Gonzales! You have 2 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e04f0aacbb20d68636",
"index": 42,
"guid": "a6990077-9274-40d5-be7a-1ddfbade8881",
"isActive": true,
"balance": "$3,159.61",
"picture": "http://placehold.it/32x32",
"age": 38,
"eyeColor": "brown",
"name": "Cherie Buchanan",
"gender": "female",
"company": "MARVANE",
"email": "cheriebuchanan@marvane.com",
"phone": "+1 (948) 457-3117",
"address": "343 Malta Street, Thatcher, New York, 2215",
"about": "Dolor dolor eu velit id pariatur magna mollit. Laborum magna dolore incididunt pariatur eiusmod ex Lorem duis voluptate velit veniam. Irure in veniam ad ipsum est aliqua ad. Eiusmod reprehenderit fugiat labore mollit fugiat exercitation occaecat reprehenderit do exercitation in consectetur.\r\n",
"registered": "2015-01-09T08:39:05 -00:00",
"latitude": -79.904618,
"longitude": 179.560453,
"tags": [
"reprehenderit",
"officia",
"non",
"ut",
"voluptate",
"fugiat",
"exercitation"
],
"friends": [
{
"id": 0,
"name": "Anna Glass"
},
{
"id": 1,
"name": "Debora Barnes"
},
{
"id": 2,
"name": "Payne West"
}
],
"greeting": "Hello, Cherie Buchanan! You have 7 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e001715680d4dd541e",
"index": 43,
"guid": "404a03ae-6529-49dc-b8e2-951681ccf627",
"isActive": true,
"balance": "$1,234.80",
"picture": "http://placehold.it/32x32",
"age": 31,
"eyeColor": "brown",
"name": "Johnnie Orr",
"gender": "female",
"company": "SCENTRIC",
"email": "johnnieorr@scentric.com",
"phone": "+1 (977) 490-2385",
"address": "215 Whitney Avenue, Dexter, Marshall Islands, 9798",
"about": "Commodo adipisicing et quis mollit nostrud nisi aliqua amet duis sunt laborum nostrud. Consectetur ullamco mollit velit sint fugiat minim ullamco consectetur dolore pariatur sit laborum. Qui ad esse duis anim dolor reprehenderit est amet aliquip. Quis ea dolore ullamco aliquip ullamco consectetur duis Lorem excepteur ut eu. Adipisicing sunt enim deserunt do excepteur ea esse ipsum enim cillum consequat. Do enim tempor mollit ut nostrud in veniam quis labore proident duis. Aliqua duis irure irure sunt ad mollit eu consequat.\r\n",
"registered": "2015-04-06T01:00:17 -01:00",
"latitude": -65.682191,
"longitude": 56.594783,
"tags": [
"dolor",
"voluptate",
"sit",
"excepteur",
"mollit",
"aliqua",
"labore"
],
"friends": [
{
"id": 0,
"name": "Duran Rowland"
},
{
"id": 1,
"name": "Guerra Morse"
},
{
"id": 2,
"name": "Stephenson Forbes"
}
],
"greeting": "Hello, Johnnie Orr! You have 5 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0f85f2da5ee425e24",
"index": 44,
"guid": "b207cfb6-e190-40c0-a7f6-8f62a955a0b5",
"isActive": true,
"balance": "$3,693.72",
"picture": "http://placehold.it/32x32",
"age": 32,
"eyeColor": "brown",
"name": "Roxanne Kirby",
"gender": "female",
"company": "BUZZMAKER",
"email": "roxannekirby@buzzmaker.com",
"phone": "+1 (819) 499-3785",
"address": "900 Albemarle Terrace, Summertown, District Of Columbia, 7918",
"about": "Excepteur incididunt amet nulla aute sunt id minim laboris sunt sunt veniam pariatur ad. Nostrud labore ut eu sunt ea voluptate deserunt sunt. Anim veniam aute magna eu labore minim proident. Laboris tempor irure consectetur velit enim proident ipsum ea enim anim et occaecat cillum fugiat. Occaecat nostrud mollit amet minim fugiat labore esse est non do excepteur fugiat magna voluptate.\r\n",
"registered": "2014-07-28T01:40:50 -01:00",
"latitude": -40.656702,
"longitude": -178.020985,
"tags": [
"velit",
"aliqua",
"pariatur",
"do",
"enim",
"aliquip",
"qui"
],
"friends": [
{
"id": 0,
"name": "Cain Benjamin"
},
{
"id": 1,
"name": "Kimberley Livingston"
},
{
"id": 2,
"name": "Bernice Schmidt"
}
],
"greeting": "Hello, Roxanne Kirby! You have 9 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0d818281f124a0db0",
"index": 45,
"guid": "2bf758f9-e3ee-4026-be96-8ad3f0e19150",
"isActive": true,
"balance": "$2,158.86",
"picture": "http://placehold.it/32x32",
"age": 30,
"eyeColor": "green",
"name": "Oneil Day",
"gender": "male",
"company": "PIVITOL",
"email": "oneilday@pivitol.com",
"phone": "+1 (876) 558-2146",
"address": "657 Concord Street, Jackpot, Mississippi, 6609",
"about": "Nostrud deserunt ex ipsum ipsum magna. Enim sunt exercitation veniam laborum enim ea veniam non est. Pariatur elit incididunt velit est cillum deserunt veniam minim exercitation. Anim reprehenderit irure nostrud quis laboris ex. Incididunt dolor exercitation do nostrud excepteur est voluptate elit. Ex incididunt excepteur in cillum sint nulla dolor duis. Fugiat laborum ut Lorem pariatur eu et nulla magna elit culpa.\r\n",
"registered": "2016-01-28T03:03:32 -00:00",
"latitude": 30.769616,
"longitude": 86.130005,
"tags": [
"enim",
"pariatur",
"in",
"qui",
"commodo",
"mollit",
"culpa"
],
"friends": [
{
"id": 0,
"name": "Erica Bauer"
},
{
"id": 1,
"name": "Noreen Sellers"
},
{
"id": 2,
"name": "Patton Mcfarland"
}
],
"greeting": "Hello, Oneil Day! You have 6 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0614bfda1fb95bba2",
"index": 46,
"guid": "55f040f3-39a9-44ba-a039-463ad9926c8c",
"isActive": true,
"balance": "$1,397.23",
"picture": "http://placehold.it/32x32",
"age": 29,
"eyeColor": "brown",
"name": "Mcmahon Hess",
"gender": "male",
"company": "KIGGLE",
"email": "mcmahonhess@kiggle.com",
"phone": "+1 (934) 486-3850",
"address": "288 Veronica Place, Rosedale, Northern Mariana Islands, 2312",
"about": "Quis nulla irure veniam duis sit velit aliquip veniam proident occaecat. Proident non pariatur et sint ex. Ullamco dolore dolore tempor eiusmod quis Lorem nostrud sit Lorem sit deserunt. Officia id quis dolor Lorem ea aliquip aliqua est elit velit sit amet dolor. Non consectetur minim adipisicing labore laboris excepteur nulla anim nostrud. Aliqua sit ex veniam laborum pariatur ipsum nostrud dolore sint. Sunt sit tempor eiusmod ex sint proident non est magna cupidatat.\r\n",
"registered": "2016-03-17T02:06:13 -00:00",
"latitude": 80.354741,
"longitude": 110.418357,
"tags": [
"nisi",
"ipsum",
"nisi",
"ullamco",
"deserunt",
"voluptate",
"in"
],
"friends": [
{
"id": 0,
"name": "Arnold Rice"
},
{
"id": 1,
"name": "Hartman Dixon"
},
{
"id": 2,
"name": "Janie Boyer"
}
],
"greeting": "Hello, Mcmahon Hess! You have 5 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0b0c52576b39ef60a",
"index": 47,
"guid": "71d9023a-9f84-4047-9b52-f170856f7d3f",
"isActive": false,
"balance": "$2,075.84",
"picture": "http://placehold.it/32x32",
"age": 36,
"eyeColor": "brown",
"name": "Kelly Bray",
"gender": "female",
"company": "ZILLANET",
"email": "kellybray@zillanet.com",
"phone": "+1 (926) 455-2510",
"address": "574 Wyona Street, Tilden, West Virginia, 4037",
"about": "Reprehenderit tempor quis velit aliqua tempor ullamco laboris aute ullamco. Cupidatat velit occaecat aute adipisicing quis. Proident excepteur et consectetur ipsum in nisi officia proident tempor veniam.\r\n",
"registered": "2015-03-21T06:27:33 -00:00",
"latitude": -24.330466,
"longitude": -118.183333,
"tags": [
"elit",
"nisi",
"magna",
"sunt",
"consequat",
"eu",
"laborum"
],
"friends": [
{
"id": 0,
"name": "Lamb Donaldson"
},
{
"id": 1,
"name": "Dodson Dickson"
},
{
"id": 2,
"name": "Graciela Guy"
}
],
"greeting": "Hello, Kelly Bray! You have 6 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0d4ebbf0f650f8f54",
"index": 48,
"guid": "617e1b51-9861-45e1-91b6-3491917ab0a0",
"isActive": false,
"balance": "$3,348.86",
"picture": "http://placehold.it/32x32",
"age": 25,
"eyeColor": "brown",
"name": "Iva Fischer",
"gender": "female",
"company": "DREAMIA",
"email": "ivafischer@dreamia.com",
"phone": "+1 (874) 565-3576",
"address": "488 Cropsey Avenue, Coloma, Illinois, 5815",
"about": "In proident mollit velit dolore esse non eu officia eiusmod ad consequat est consectetur. Proident mollit ad esse officia quis magna consequat eu sit incididunt sunt excepteur. Ullamco eu nisi exercitation consectetur veniam officia consequat. Ex ea voluptate aliqua eiusmod est eiusmod irure officia fugiat officia do excepteur commodo ea.\r\n",
"registered": "2014-08-06T03:37:45 -01:00",
"latitude": 4.279188,
"longitude": -145.844052,
"tags": [
"enim",
"culpa",
"ut",
"ullamco",
"nostrud",
"ullamco",
"et"
],
"friends": [
{
"id": 0,
"name": "Cantrell Blair"
},
{
"id": 1,
"name": "Ramos Kelly"
},
{
"id": 2,
"name": "Herminia Frost"
}
],
"greeting": "Hello, Iva Fischer! You have 10 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0d3a5c1f4f9735793",
"index": 49,
"guid": "18b4eb26-e48a-4838-882e-cf161146807c",
"isActive": false,
"balance": "$1,922.43",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "brown",
"name": "Gibbs Garza",
"gender": "male",
"company": "ZAGGLES",
"email": "gibbsgarza@zaggles.com",
"phone": "+1 (854) 533-2394",
"address": "254 Leonard Street, Kersey, Florida, 897",
"about": "Non est reprehenderit consectetur qui. Sunt ut magna proident non do mollit quis aliquip nostrud adipisicing officia labore aliquip. Labore qui excepteur elit aute deserunt nostrud consectetur veniam ipsum nisi esse ullamco. Laborum veniam et nostrud pariatur veniam do aute. Elit quis commodo enim ex reprehenderit amet laboris quis dolore.\r\n",
"registered": "2016-07-28T01:31:10 -01:00",
"latitude": -44.075335,
"longitude": -42.893033,
"tags": [
"incididunt",
"consequat",
"laboris",
"reprehenderit",
"culpa",
"quis",
"occaecat"
],
"friends": [
{
"id": 0,
"name": "Deloris Houston"
},
{
"id": 1,
"name": "Jodi Pittman"
},
{
"id": 2,
"name": "Diana Dodson"
}
],
"greeting": "Hello, Gibbs Garza! You have 9 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0548c0b0eb2a733db",
"index": 50,
"guid": "ad67ef06-23e6-4647-8004-9ba9743303a9",
"isActive": true,
"balance": "$1,244.34",
"picture": "http://placehold.it/32x32",
"age": 33,
"eyeColor": "green",
"name": "Marylou Bernard",
"gender": "female",
"company": "ZENTHALL",
"email": "maryloubernard@zenthall.com",
"phone": "+1 (952) 571-3544",
"address": "938 Varick Avenue, Nettie, Pennsylvania, 7183",
"about": "Duis ea sint sint Lorem. Incididunt elit laboris elit laborum. Incididunt eiusmod anim dolor ipsum aute occaecat ad nulla est duis pariatur quis. Minim enim et fugiat minim ex eu ipsum fugiat magna.\r\n",
"registered": "2015-11-08T05:44:56 -00:00",
"latitude": 89.449352,
"longitude": -38.858046,
"tags": [
"reprehenderit",
"deserunt",
"est",
"sit",
"aliquip",
"duis",
"cillum"
],
"friends": [
{
"id": 0,
"name": "Levine Myers"
},
{
"id": 1,
"name": "Harriet Emerson"
},
{
"id": 2,
"name": "Nicholson Irwin"
}
],
"greeting": "Hello, Marylou Bernard! You have 10 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0355c0521d739d369",
"index": 51,
"guid": "3c8a780d-843f-4d7f-92dd-93133e4b83e1",
"isActive": false,
"balance": "$3,138.76",
"picture": "http://placehold.it/32x32",
"age": 34,
"eyeColor": "blue",
"name": "Berta Cash",
"gender": "female",
"company": "ASSISTIA",
"email": "bertacash@assistia.com",
"phone": "+1 (881) 581-2413",
"address": "835 Williamsburg Street, Coleville, Montana, 4578",
"about": "Officia officia nulla ipsum dolor id nisi sint elit nulla anim. Proident fugiat do cupidatat commodo. Consequat non consequat voluptate reprehenderit minim magna veniam sunt.\r\n",
"registered": "2016-05-19T01:38:26 -01:00",
"latitude": -87.065213,
"longitude": -73.949279,
"tags": [
"minim",
"culpa",
"ipsum",
"aliquip",
"consectetur",
"qui",
"consectetur"
],
"friends": [
{
"id": 0,
"name": "Gillespie Doyle"
},
{
"id": 1,
"name": "Susanne Hutchinson"
},
{
"id": 2,
"name": "Terrell Humphrey"
}
],
"greeting": "Hello, Berta Cash! You have 5 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0af5e764fd1106712",
"index": 52,
"guid": "ab6b15cd-234b-4c66-94f3-cab399fce36a",
"isActive": true,
"balance": "$3,796.65",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "green",
"name": "Juliette Dyer",
"gender": "female",
"company": "SQUISH",
"email": "juliettedyer@squish.com",
"phone": "+1 (913) 532-2796",
"address": "466 Montgomery Place, Grill, Guam, 1332",
"about": "Minim sit dolore non laboris id. Aliquip incididunt consectetur voluptate laboris velit commodo in. Ea ea pariatur fugiat incididunt. Enim ea pariatur incididunt proident cillum officia enim sit exercitation id exercitation ea eiusmod nulla. Cupidatat tempor minim nostrud nulla. Voluptate ea laborum aliquip nisi cillum cupidatat. Cupidatat consequat velit nostrud aliqua.\r\n",
"registered": "2014-01-06T06:52:22 -00:00",
"latitude": -43.894999,
"longitude": 118.046458,
"tags": [
"do",
"dolor",
"nostrud",
"duis",
"eiusmod",
"exercitation",
"excepteur"
],
"friends": [
{
"id": 0,
"name": "Walter Hart"
},
{
"id": 1,
"name": "Mccoy Merritt"
},
{
"id": 2,
"name": "Shelia Wilkinson"
}
],
"greeting": "Hello, Juliette Dyer! You have 6 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e056e31eee58b0c428",
"index": 53,
"guid": "cb62aafe-a0cd-457c-bf77-646ad78e3713",
"isActive": true,
"balance": "$1,340.29",
"picture": "http://placehold.it/32x32",
"age": 27,
"eyeColor": "blue",
"name": "Beverly Vargas",
"gender": "female",
"company": "BRISTO",
"email": "beverlyvargas@bristo.com",
"phone": "+1 (944) 527-2844",
"address": "393 Driggs Avenue, Manchester, Missouri, 764",
"about": "Qui ipsum ex dolore tempor veniam occaecat proident. Ullamco nostrud id sit sunt anim minim incididunt Lorem. Occaecat nulla deserunt ut aliquip. Nostrud consectetur elit ipsum sunt in fugiat deserunt excepteur dolore. Proident in dolor pariatur sint aliquip velit aliqua non ex fugiat laboris eu deserunt quis. Ullamco proident commodo tempor labore sunt ea enim velit ullamco qui deserunt adipisicing. Aute commodo ipsum labore Lorem in est incididunt aute voluptate voluptate labore minim sunt ut.\r\n",
"registered": "2015-11-27T04:24:26 -00:00",
"latitude": -1.807115,
"longitude": 41.187021,
"tags": [
"sunt",
"anim",
"dolor",
"dolor",
"aute",
"proident",
"mollit"
],
"friends": [
{
"id": 0,
"name": "Cross Cohen"
},
{
"id": 1,
"name": "Brennan Miller"
},
{
"id": 2,
"name": "Kaye Chen"
}
],
"greeting": "Hello, Beverly Vargas! You have 2 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0ce01bad732576c2a",
"index": 54,
"guid": "e1975718-1787-4498-9de9-d38e5b430ebf",
"isActive": false,
"balance": "$2,984.58",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "green",
"name": "Golden Hartman",
"gender": "male",
"company": "QABOOS",
"email": "goldenhartman@qaboos.com",
"phone": "+1 (941) 517-3259",
"address": "816 Beacon Court, Castleton, Indiana, 1599",
"about": "Aliqua nisi fugiat enim fugiat ex mollit. Non ad ullamco irure deserunt exercitation in non nisi esse deserunt in ea irure. Non pariatur voluptate proident in enim officia anim excepteur do cillum. Minim Lorem exercitation cupidatat ad Lorem. Ut ad nostrud nisi aliqua incididunt non. Ipsum et mollit aliqua fugiat fugiat officia. Eiusmod voluptate consectetur consequat nulla deserunt amet eu eiusmod et culpa est.\r\n",
"registered": "2014-02-21T01:02:34 -00:00",
"latitude": -66.459423,
"longitude": 55.50342,
"tags": [
"aute",
"sunt",
"duis",
"sint",
"esse",
"sit",
"aliquip"
],
"friends": [
{
"id": 0,
"name": "Valenzuela Dunlap"
},
{
"id": 1,
"name": "Logan Wood"
},
{
"id": 2,
"name": "Sara Bryan"
}
],
"greeting": "Hello, Golden Hartman! You have 1 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e08470f72e37a5149d",
"index": 55,
"guid": "069b007f-9809-4ab4-a891-0fc39a182a72",
"isActive": true,
"balance": "$1,319.54",
"picture": "http://placehold.it/32x32",
"age": 31,
"eyeColor": "blue",
"name": "Angel Long",
"gender": "female",
"company": "XPLOR",
"email": "angellong@xplor.com",
"phone": "+1 (914) 564-2587",
"address": "525 Kermit Place, Reinerton, Tennessee, 5477",
"about": "Fugiat nisi commodo deserunt reprehenderit. Amet enim ex est non cupidatat. Dolore laborum proident labore minim sunt deserunt laboris officia aute enim in culpa. Labore sint est non in eiusmod. Laborum occaecat ut cupidatat ut elit deserunt ex. Nisi occaecat ut minim ex nisi proident.\r\n",
"registered": "2016-02-15T09:22:15 -00:00",
"latitude": -76.066077,
"longitude": -59.767087,
"tags": [
"do",
"quis",
"laborum",
"culpa",
"sunt",
"ullamco",
"reprehenderit"
],
"friends": [
{
"id": 0,
"name": "Sharlene Blackwell"
},
{
"id": 1,
"name": "Rochelle Douglas"
},
{
"id": 2,
"name": "Mullins Hill"
}
],
"greeting": "Hello, Angel Long! You have 1 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e07f1736323a768cba",
"index": 56,
"guid": "fb58dc5a-212c-4714-886c-3ffeedee533c",
"isActive": true,
"balance": "$3,727.88",
"picture": "http://placehold.it/32x32",
"age": 32,
"eyeColor": "green",
"name": "Robbie Camacho",
"gender": "female",
"company": "PUSHCART",
"email": "robbiecamacho@pushcart.com",
"phone": "+1 (903) 519-3473",
"address": "110 Dahl Court, Coalmont, New Hampshire, 8717",
"about": "Ad ea quis nisi culpa. Tempor et quis amet laborum ipsum aute aliquip aliquip nisi ut veniam. Est cupidatat voluptate aute sunt duis nostrud laborum incididunt mollit. Deserunt sit incididunt sit occaecat non nisi id nostrud proident consectetur sit eu do. Incididunt proident sint sunt laborum excepteur magna enim. Qui et nostrud laboris amet amet eu veniam esse pariatur. Esse enim in commodo ut excepteur anim velit.\r\n",
"registered": "2015-04-16T11:26:36 -01:00",
"latitude": -11.452945,
"longitude": 28.089439,
"tags": [
"duis",
"sunt",
"non",
"culpa",
"eu",
"ut",
"dolore"
],
"friends": [
{
"id": 0,
"name": "Lowe Carlson"
},
{
"id": 1,
"name": "Richardson Strickland"
},
{
"id": 2,
"name": "Suarez Tyler"
}
],
"greeting": "Hello, Robbie Camacho! You have 4 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e048239bce67dda88a",
"index": 57,
"guid": "361cbd4c-a319-4a0d-ae34-8d370d867d86",
"isActive": true,
"balance": "$1,266.14",
"picture": "http://placehold.it/32x32",
"age": 33,
"eyeColor": "green",
"name": "Manning Cruz",
"gender": "male",
"company": "NEBULEAN",
"email": "manningcruz@nebulean.com",
"phone": "+1 (883) 465-3552",
"address": "146 Merit Court, Lemoyne, Hawaii, 2472",
"about": "Sunt incididunt officia adipisicing id velit. Deserunt do pariatur ea nisi. Proident amet ea qui consectetur non Lorem proident exercitation occaecat anim. Tempor excepteur aliqua eiusmod sit aliqua ea dolore fugiat ex ullamco. Amet magna consequat cupidatat fugiat cupidatat occaecat anim sunt ut non.\r\n",
"registered": "2014-06-03T07:23:07 -01:00",
"latitude": -38.724862,
"longitude": -90.509303,
"tags": [
"consequat",
"velit",
"deserunt",
"Lorem",
"labore",
"laborum",
"qui"
],
"friends": [
{
"id": 0,
"name": "Celia Boyle"
},
{
"id": 1,
"name": "Rosales Blankenship"
},
{
"id": 2,
"name": "Terra Hinton"
}
],
"greeting": "Hello, Manning Cruz! You have 6 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e02b428b6cd5da3de5",
"index": 58,
"guid": "a5207b6d-5ebb-4ea0-a11c-19e7e182b9ae",
"isActive": true,
"balance": "$1,182.87",
"picture": "http://placehold.it/32x32",
"age": 40,
"eyeColor": "blue",
"name": "Manuela Sullivan",
"gender": "female",
"company": "SIGNITY",
"email": "manuelasullivan@signity.com",
"phone": "+1 (858) 536-2441",
"address": "787 Bergen Court, Oneida, Rhode Island, 2068",
"about": "Proident non deserunt fugiat id fugiat cillum et elit consectetur eu. Ut aliqua tempor deserunt velit sit enim ex anim anim aute do. Culpa cillum culpa ullamco consequat consequat. Velit ad nisi occaecat aliqua qui qui. Sint aliquip laboris elit mollit ullamco eu fugiat aute esse sunt cillum cupidatat ad. Exercitation esse incididunt laborum enim fugiat non minim.\r\n",
"registered": "2015-11-24T09:07:36 -00:00",
"latitude": -59.546369,
"longitude": -27.04345,
"tags": [
"veniam",
"excepteur",
"dolore",
"in",
"reprehenderit",
"consectetur",
"cillum"
],
"friends": [
{
"id": 0,
"name": "Harper Becker"
},
{
"id": 1,
"name": "Prince Roman"
},
{
"id": 2,
"name": "Melva Neal"
}
],
"greeting": "Hello, Manuela Sullivan! You have 3 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0ed86cb59146240af",
"index": 59,
"guid": "14f076a0-332b-4847-81d2-18ea1ebb1947",
"isActive": false,
"balance": "$1,978.65",
"picture": "http://placehold.it/32x32",
"age": 24,
"eyeColor": "blue",
"name": "Glover Keith",
"gender": "male",
"company": "PLASMOSIS",
"email": "gloverkeith@plasmosis.com",
"phone": "+1 (979) 405-3826",
"address": "706 Elton Street, Dupuyer, New Jersey, 2463",
"about": "Eu aliquip dolor occaecat eu enim. Consequat fugiat veniam anim anim ut cupidatat labore cupidatat deserunt. Amet ad dolor esse in ut cupidatat occaecat ea enim id. Proident ex est mollit nisi qui culpa ea est nostrud ipsum non ad. Culpa ex nostrud ut aliqua sit officia ex culpa et nisi minim duis duis est. Consequat occaecat velit laboris culpa ex incididunt amet. In pariatur dolor eiusmod sunt et et sit duis ullamco et incididunt.\r\n",
"registered": "2014-04-13T08:57:03 -01:00",
"latitude": 1.010568,
"longitude": 54.436644,
"tags": [
"mollit",
"magna",
"amet",
"dolore",
"reprehenderit",
"sint",
"fugiat"
],
"friends": [
{
"id": 0,
"name": "Schroeder Murphy"
},
{
"id": 1,
"name": "Petra Hines"
},
{
"id": 2,
"name": "Hanson Cooke"
}
],
"greeting": "Hello, Glover Keith! You have 5 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0ff8c87b2b087155b",
"index": 60,
"guid": "a0d6e148-1adc-410b-a6ae-356f9abc776f",
"isActive": false,
"balance": "$1,566.63",
"picture": "http://placehold.it/32x32",
"age": 25,
"eyeColor": "brown",
"name": "Hillary Ward",
"gender": "female",
"company": "AUSTECH",
"email": "hillaryward@austech.com",
"phone": "+1 (972) 507-2763",
"address": "577 Jamison Lane, Harviell, North Carolina, 6285",
"about": "Consectetur commodo consequat amet reprehenderit. Ea ea exercitation aliquip dolore aute nisi dolor veniam non ut incididunt. Laborum dolore ad cillum ullamco. Laboris elit officia est nisi tempor. Incididunt aliqua est proident irure nostrud irure adipisicing est sunt cillum do voluptate cupidatat. Non ea veniam officia fugiat amet nostrud. Veniam cupidatat nisi nostrud duis quis duis sunt ea officia et laborum.\r\n",
"registered": "2016-05-25T11:51:01 -01:00",
"latitude": -16.097329,
"longitude": -64.099402,
"tags": [
"nostrud",
"amet",
"ullamco",
"ullamco",
"ea",
"Lorem",
"incididunt"
],
"friends": [
{
"id": 0,
"name": "Ortiz Stewart"
},
{
"id": 1,
"name": "Booker Hewitt"
},
{
"id": 2,
"name": "Lea Hyde"
}
],
"greeting": "Hello, Hillary Ward! You have 8 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e09d607d06f0b6d014",
"index": 61,
"guid": "891bd182-8242-4002-b04a-fcba21f723bf",
"isActive": true,
"balance": "$1,417.19",
"picture": "http://placehold.it/32x32",
"age": 38,
"eyeColor": "green",
"name": "Hood Mcclure",
"gender": "male",
"company": "FROSNEX",
"email": "hoodmcclure@frosnex.com",
"phone": "+1 (997) 491-3049",
"address": "831 Hampton Avenue, Sexton, Massachusetts, 4239",
"about": "Dolore ullamco consequat magna et ad anim reprehenderit minim. Irure ullamco elit voluptate tempor consequat ut sint fugiat. Incididunt consequat enim ipsum anim.\r\n",
"registered": "2014-07-30T06:33:40 -01:00",
"latitude": -38.68367,
"longitude": -146.158291,
"tags": [
"est",
"et",
"esse",
"amet",
"incididunt",
"velit",
"enim"
],
"friends": [
{
"id": 0,
"name": "Bartlett Munoz"
},
{
"id": 1,
"name": "Elma Rios"
},
{
"id": 2,
"name": "Doyle Hall"
}
],
"greeting": "Hello, Hood Mcclure! You have 2 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0ca33437bf9683fb5",
"index": 62,
"guid": "437beddf-8f32-43c9-a801-b69398bb3d93",
"isActive": false,
"balance": "$2,837.79",
"picture": "http://placehold.it/32x32",
"age": 22,
"eyeColor": "green",
"name": "Lucille Hogan",
"gender": "female",
"company": "BEDLAM",
"email": "lucillehogan@bedlam.com",
"phone": "+1 (892) 447-3611",
"address": "200 Richards Street, Chalfant, Palau, 3648",
"about": "Do dolore sunt ipsum eiusmod aute veniam minim. Esse id velit eu esse. Laboris sit elit labore sunt ea. Veniam aliquip exercitation nostrud sint eiusmod voluptate veniam nisi occaecat.\r\n",
"registered": "2014-05-19T11:29:20 -01:00",
"latitude": -52.054303,
"longitude": -179.77118,
"tags": [
"est",
"ipsum",
"velit",
"minim",
"nulla",
"deserunt",
"consequat"
],
"friends": [
{
"id": 0,
"name": "Finch Booker"
},
{
"id": 1,
"name": "Underwood Knowles"
},
{
"id": 2,
"name": "Bender Best"
}
],
"greeting": "Hello, Lucille Hogan! You have 8 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0e1db6e099b15fcd3",
"index": 63,
"guid": "45d08c06-58c3-4631-8fc1-c5d433eaa790",
"isActive": false,
"balance": "$3,831.67",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "green",
"name": "Aline Morrow",
"gender": "female",
"company": "SLAX",
"email": "alinemorrow@slax.com",
"phone": "+1 (805) 524-2600",
"address": "231 Dank Court, Needmore, Wyoming, 1054",
"about": "Ut nostrud veniam tempor voluptate. Cupidatat consectetur quis ex do excepteur voluptate nisi veniam ipsum cupidatat cupidatat cillum enim do. Fugiat ut quis commodo est adipisicing deserunt ut amet sit voluptate laboris. Eu aliqua qui minim eu proident sunt.\r\n",
"registered": "2014-02-23T03:09:32 -00:00",
"latitude": 34.065632,
"longitude": 159.260434,
"tags": [
"eiusmod",
"elit",
"non",
"ad",
"exercitation",
"cupidatat",
"tempor"
],
"friends": [
{
"id": 0,
"name": "Sears Pratt"
},
{
"id": 1,
"name": "Tabatha Glenn"
},
{
"id": 2,
"name": "Fleming Noble"
}
],
"greeting": "Hello, Aline Morrow! You have 8 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0cf19812f3ca34272",
"index": 64,
"guid": "4621104a-42db-446d-9677-3aa09137e565",
"isActive": true,
"balance": "$1,277.44",
"picture": "http://placehold.it/32x32",
"age": 24,
"eyeColor": "brown",
"name": "Sexton Contreras",
"gender": "male",
"company": "QUILITY",
"email": "sextoncontreras@quility.com",
"phone": "+1 (805) 519-3133",
"address": "809 Fay Court, Cavalero, Federated States Of Micronesia, 3309",
"about": "Dolor veniam incididunt proident est qui veniam aliqua eu pariatur. Sunt aliquip laborum deserunt deserunt eiusmod culpa tempor mollit laboris consequat cillum sit consequat. Esse sit consequat cupidatat fugiat ullamco.\r\n",
"registered": "2014-10-18T03:41:08 -01:00",
"latitude": 29.832296,
"longitude": -119.115401,
"tags": [
"id",
"nisi",
"fugiat",
"et",
"aliqua",
"dolor",
"reprehenderit"
],
"friends": [
{
"id": 0,
"name": "Addie Johnston"
},
{
"id": 1,
"name": "Lang Graves"
},
{
"id": 2,
"name": "Garrison Hodge"
}
],
"greeting": "Hello, Sexton Contreras! You have 1 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e039d28753188ad0ad",
"index": 65,
"guid": "65490eb8-dec4-473a-a756-07c3e965b22c",
"isActive": true,
"balance": "$2,932.64",
"picture": "http://placehold.it/32x32",
"age": 35,
"eyeColor": "green",
"name": "Lora Shepherd",
"gender": "female",
"company": "KAGGLE",
"email": "lorashepherd@kaggle.com",
"phone": "+1 (895) 494-3098",
"address": "404 President Street, Brule, Alaska, 1187",
"about": "Minim nulla duis duis cillum occaecat sint qui et cillum ad. Laboris laborum aute esse et dolor. Id tempor pariatur consectetur magna non nostrud.\r\n",
"registered": "2016-02-02T03:31:13 -00:00",
"latitude": -51.952869,
"longitude": 139.386084,
"tags": [
"in",
"sunt",
"aliqua",
"labore",
"irure",
"culpa",
"magna"
],
"friends": [
{
"id": 0,
"name": "Hodges Newman"
},
{
"id": 1,
"name": "Sanchez Woods"
},
{
"id": 2,
"name": "Farley Jensen"
}
],
"greeting": "Hello, Lora Shepherd! You have 7 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0751e37b3046d4f00",
"index": 66,
"guid": "44d70a42-a872-4d48-8a29-7a5fe8622bb4",
"isActive": true,
"balance": "$1,039.22",
"picture": "http://placehold.it/32x32",
"age": 40,
"eyeColor": "green",
"name": "Mejia Solomon",
"gender": "male",
"company": "PROSURE",
"email": "mejiasolomon@prosure.com",
"phone": "+1 (916) 515-3916",
"address": "950 Sullivan Street, Hayes, Louisiana, 7480",
"about": "Cupidatat sunt velit ex elit sint ex ea consequat occaecat aute culpa esse laboris officia. Ea adipisicing incididunt duis velit exercitation laborum irure quis. Sunt sunt ipsum consectetur dolor elit nisi do.\r\n",
"registered": "2015-06-24T06:58:22 -01:00",
"latitude": -15.413523,
"longitude": 15.643053,
"tags": [
"fugiat",
"culpa",
"ullamco",
"minim",
"nostrud",
"occaecat",
"laborum"
],
"friends": [
{
"id": 0,
"name": "Emerson Bryant"
},
{
"id": 1,
"name": "Alberta Haynes"
},
{
"id": 2,
"name": "Courtney Turner"
}
],
"greeting": "Hello, Mejia Solomon! You have 2 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0f9a796946c5cc534",
"index": 67,
"guid": "a369f641-65a9-4ab7-a9b4-18ed890507d7",
"isActive": false,
"balance": "$2,351.55",
"picture": "http://placehold.it/32x32",
"age": 20,
"eyeColor": "brown",
"name": "Berg Dean",
"gender": "male",
"company": "VIDTO",
"email": "bergdean@vidto.com",
"phone": "+1 (936) 440-3744",
"address": "488 Boerum Place, Wawona, Nevada, 1579",
"about": "Excepteur culpa in aliqua enim pariatur occaecat. Labore commodo aute irure laborum reprehenderit tempor in eiusmod velit Lorem proident officia id. Dolore culpa est non ipsum fugiat magna in aliquip sunt. Laboris elit labore aliqua consectetur. Occaecat do nostrud veniam Lorem nulla. Veniam ea reprehenderit consequat occaecat tempor labore.\r\n",
"registered": "2015-04-18T10:25:48 -01:00",
"latitude": 70.649558,
"longitude": -98.622436,
"tags": [
"labore",
"veniam",
"ut",
"do",
"sunt",
"minim",
"minim"
],
"friends": [
{
"id": 0,
"name": "Bowman Hoffman"
},
{
"id": 1,
"name": "Beulah Ray"
},
{
"id": 2,
"name": "Savannah Lang"
}
],
"greeting": "Hello, Berg Dean! You have 9 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e00e3810d2abf67039",
"index": 68,
"guid": "2ca0bc78-1dce-482e-8cb3-1b72feaf3115",
"isActive": true,
"balance": "$3,047.63",
"picture": "http://placehold.it/32x32",
"age": 29,
"eyeColor": "green",
"name": "Zimmerman Mcguire",
"gender": "male",
"company": "MAZUDA",
"email": "zimmermanmcguire@mazuda.com",
"phone": "+1 (888) 501-3241",
"address": "909 Saratoga Avenue, Guilford, Georgia, 4937",
"about": "Non Lorem fugiat veniam consequat commodo. Tempor officia anim proident ex laboris. Enim magna laborum reprehenderit ad dolore do pariatur irure fugiat ad. Irure dolore id do ullamco sit Lorem aliqua consequat et commodo et tempor tempor deserunt. Nulla eu qui voluptate amet eiusmod voluptate sunt aute adipisicing. Sunt ipsum sit adipisicing proident aliquip consequat occaecat veniam ullamco nulla excepteur.\r\n",
"registered": "2015-12-21T05:44:26 -00:00",
"latitude": -42.330322,
"longitude": -80.17566,
"tags": [
"mollit",
"magna",
"irure",
"adipisicing",
"amet",
"duis",
"exercitation"
],
"friends": [
{
"id": 0,
"name": "Karyn Ramos"
},
{
"id": 1,
"name": "Rojas Hancock"
},
{
"id": 2,
"name": "Tami Reyes"
}
],
"greeting": "Hello, Zimmerman Mcguire! You have 2 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0fa0bd84fd713d334",
"index": 69,
"guid": "2f69c1c7-659c-49fe-a349-73a57d4af112",
"isActive": true,
"balance": "$3,853.20",
"picture": "http://placehold.it/32x32",
"age": 20,
"eyeColor": "green",
"name": "Phillips Cote",
"gender": "male",
"company": "ENERVATE",
"email": "phillipscote@enervate.com",
"phone": "+1 (902) 453-2129",
"address": "133 Seaview Avenue, Lumberton, Utah, 4187",
"about": "Sit est commodo dolor nulla irure duis excepteur labore cupidatat officia. Amet aliquip enim officia fugiat ipsum amet minim ipsum aliqua culpa ipsum irure. Magna eu voluptate eu eu exercitation. Magna exercitation consectetur elit esse minim enim consectetur sint. Irure fugiat laborum magna qui ad sint ea mollit magna proident et magna. Irure Lorem ut enim id aliqua nostrud amet.\r\n",
"registered": "2015-10-05T07:29:43 -01:00",
"latitude": 31.313816,
"longitude": 98.358011,
"tags": [
"irure",
"cillum",
"exercitation",
"mollit",
"enim",
"aute",
"laborum"
],
"friends": [
{
"id": 0,
"name": "Robyn Castaneda"
},
{
"id": 1,
"name": "Cole Deleon"
},
{
"id": 2,
"name": "Marva Fuentes"
}
],
"greeting": "Hello, Phillips Cote! You have 5 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0f2471ce13c153453",
"index": 70,
"guid": "cbfd71a1-2bc2-4c96-943e-58db8e68e86d",
"isActive": false,
"balance": "$2,678.33",
"picture": "http://placehold.it/32x32",
"age": 27,
"eyeColor": "green",
"name": "Evangeline Hatfield",
"gender": "female",
"company": "VIRVA",
"email": "evangelinehatfield@virva.com",
"phone": "+1 (931) 590-2003",
"address": "381 Carlton Avenue, Elrama, Virginia, 9223",
"about": "Ullamco deserunt sint amet sint adipisicing consequat. Enim labore id minim reprehenderit ut ullamco. Lorem non cupidatat culpa ex. Do occaecat laborum id cillum est dolore duis proident aute labore laborum.\r\n",
"registered": "2014-05-26T10:23:05 -01:00",
"latitude": -33.84015,
"longitude": -73.41226,
"tags": [
"sit",
"duis",
"aliqua",
"pariatur",
"voluptate",
"culpa",
"aliqua"
],
"friends": [
{
"id": 0,
"name": "Colon Estrada"
},
{
"id": 1,
"name": "Ellen Vance"
},
{
"id": 2,
"name": "Reynolds Park"
}
],
"greeting": "Hello, Evangeline Hatfield! You have 10 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e061cf29a979efa785",
"index": 71,
"guid": "633864bf-bc0e-4859-8e34-af06c38861db",
"isActive": true,
"balance": "$1,071.05",
"picture": "http://placehold.it/32x32",
"age": 36,
"eyeColor": "brown",
"name": "Knowles Delacruz",
"gender": "male",
"company": "ELENTRIX",
"email": "knowlesdelacruz@elentrix.com",
"phone": "+1 (858) 471-2941",
"address": "740 Cypress Court, Shawmut, Kansas, 1468",
"about": "Do nisi pariatur esse do eu consectetur ut proident ex reprehenderit tempor do reprehenderit dolor. Nisi enim laborum et do tempor amet mollit non consectetur. Excepteur veniam culpa enim aliqua culpa voluptate reprehenderit eu. Lorem dolore commodo exercitation minim minim tempor in. Voluptate nulla dolor est sint eiusmod. Aute cillum dolore consequat cillum labore ullamco Lorem ea. Pariatur labore ipsum fugiat culpa deserunt cupidatat laboris ad aute sunt do.\r\n",
"registered": "2015-07-18T02:43:03 -01:00",
"latitude": 35.621488,
"longitude": -95.403701,
"tags": [
"do",
"eiusmod",
"enim",
"sint",
"voluptate",
"voluptate",
"cupidatat"
],
"friends": [
{
"id": 0,
"name": "Sonya Franco"
},
{
"id": 1,
"name": "Rosario Cotton"
},
{
"id": 2,
"name": "Evans Mccall"
}
],
"greeting": "Hello, Knowles Delacruz! You have 9 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0571000dc5935f11a",
"index": 72,
"guid": "31aaeb7d-cf73-4fe9-a29e-b412ce8dacb2",
"isActive": false,
"balance": "$2,722.63",
"picture": "http://placehold.it/32x32",
"age": 24,
"eyeColor": "brown",
"name": "Cummings Flynn",
"gender": "male",
"company": "IDETICA",
"email": "cummingsflynn@idetica.com",
"phone": "+1 (839) 571-3595",
"address": "570 Anchorage Place, Dola, Iowa, 9955",
"about": "Aliquip elit eiusmod mollit ex amet non sunt ex. Quis sit do minim adipisicing do excepteur id non voluptate aute ut cupidatat velit deserunt. Tempor amet labore qui commodo aute eiusmod labore irure voluptate dolore veniam.\r\n",
"registered": "2014-08-26T03:33:35 -01:00",
"latitude": -45.16368,
"longitude": -73.376605,
"tags": [
"sunt",
"quis",
"dolore",
"quis",
"culpa",
"quis",
"dolore"
],
"friends": [
{
"id": 0,
"name": "Oneal Rosales"
},
{
"id": 1,
"name": "Christensen Wilcox"
},
{
"id": 2,
"name": "Serrano Marshall"
}
],
"greeting": "Hello, Cummings Flynn! You have 10 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0b3e6de2740fabd0f",
"index": 73,
"guid": "c880e684-b62d-4807-b85e-518cc0045358",
"isActive": true,
"balance": "$2,828.90",
"picture": "http://placehold.it/32x32",
"age": 35,
"eyeColor": "brown",
"name": "Beasley Farley",
"gender": "male",
"company": "CAXT",
"email": "beasleyfarley@caxt.com",
"phone": "+1 (991) 528-3934",
"address": "153 Beaumont Street, Kilbourne, Michigan, 3993",
"about": "Nostrud cupidatat amet enim cupidatat Lorem. Amet esse ut dolor nostrud officia officia officia reprehenderit reprehenderit duis proident ad occaecat. Reprehenderit incididunt ex amet nostrud dolor quis est sunt amet. Officia elit aliqua consequat ullamco nostrud officia ad fugiat labore excepteur ad.\r\n",
"registered": "2015-01-11T01:52:33 -00:00",
"latitude": -39.757594,
"longitude": 144.458542,
"tags": [
"ea",
"tempor",
"Lorem",
"ad",
"irure",
"culpa",
"irure"
],
"friends": [
{
"id": 0,
"name": "Brandi Ruiz"
},
{
"id": 1,
"name": "Deena Burke"
},
{
"id": 2,
"name": "Briana Key"
}
],
"greeting": "Hello, Beasley Farley! You have 8 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e01c03a42a97465443",
"index": 74,
"guid": "edaa2407-1378-496b-973c-7a867e78d4cd",
"isActive": true,
"balance": "$1,640.89",
"picture": "http://placehold.it/32x32",
"age": 37,
"eyeColor": "brown",
"name": "Judy Berry",
"gender": "female",
"company": "ENDICIL",
"email": "judyberry@endicil.com",
"phone": "+1 (976) 444-2283",
"address": "848 Herkimer Court, Deputy, South Dakota, 1507",
"about": "Et laboris laborum exercitation esse id id nisi culpa dolore exercitation incididunt laboris culpa eiusmod. Nostrud id cillum incididunt veniam in elit anim magna sit sint voluptate minim proident consequat. Do aliqua nulla magna est tempor sint do. Ad irure incididunt consequat quis consequat qui nulla nostrud. Commodo cupidatat exercitation veniam officia velit reprehenderit ex irure do ad commodo minim.\r\n",
"registered": "2015-03-10T03:59:20 -00:00",
"latitude": 13.764125,
"longitude": -168.721201,
"tags": [
"deserunt",
"officia",
"voluptate",
"aliqua",
"sint",
"excepteur",
"ipsum"
],
"friends": [
{
"id": 0,
"name": "Casey Perry"
},
{
"id": 1,
"name": "Imelda Garrett"
},
{
"id": 2,
"name": "Mollie Pearson"
}
],
"greeting": "Hello, Judy Berry! You have 3 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0f621f4123348a250",
"index": 75,
"guid": "c7193d33-5432-40e0-9c84-f8da110d5061",
"isActive": false,
"balance": "$1,114.51",
"picture": "http://placehold.it/32x32",
"age": 39,
"eyeColor": "brown",
"name": "Joanna Davidson",
"gender": "female",
"company": "SPLINX",
"email": "joannadavidson@splinx.com",
"phone": "+1 (907) 576-2435",
"address": "108 Kings Hwy, Yonah, Colorado, 3516",
"about": "Aute cillum aliquip eiusmod laborum ea esse do pariatur tempor anim id ex. Reprehenderit quis aute minim tempor. Id eiusmod consectetur non nulla labore voluptate. Cupidatat adipisicing occaecat consectetur sunt culpa elit reprehenderit aliqua. Nulla aliquip enim do elit pariatur id velit.\r\n",
"registered": "2014-01-29T02:21:58 -00:00",
"latitude": 72.711235,
"longitude": 54.596397,
"tags": [
"minim",
"laboris",
"adipisicing",
"minim",
"et",
"exercitation",
"elit"
],
"friends": [
{
"id": 0,
"name": "Tanner Paul"
},
{
"id": 1,
"name": "Schneider Sargent"
},
{
"id": 2,
"name": "Brady Nieves"
}
],
"greeting": "Hello, Joanna Davidson! You have 6 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e05854075543d3581b",
"index": 76,
"guid": "aae5a70d-22b6-47a6-8f75-a22c00f7a276",
"isActive": false,
"balance": "$1,187.24",
"picture": "http://placehold.it/32x32",
"age": 32,
"eyeColor": "brown",
"name": "Mariana Kane",
"gender": "female",
"company": "SKYPLEX",
"email": "marianakane@skyplex.com",
"phone": "+1 (809) 501-2460",
"address": "135 Atkins Avenue, Grayhawk, Oregon, 1827",
"about": "Ea labore ad ut laborum id et irure ut cupidatat tempor. Nostrud reprehenderit adipisicing et veniam proident cillum veniam ullamco dolore proident consectetur. Anim esse nisi pariatur duis aute.\r\n",
"registered": "2016-06-05T05:51:55 -01:00",
"latitude": 15.151043,
"longitude": 118.171912,
"tags": [
"fugiat",
"proident",
"adipisicing",
"pariatur",
"proident",
"amet",
"amet"
],
"friends": [
{
"id": 0,
"name": "Corine Hicks"
},
{
"id": 1,
"name": "Chavez Norton"
},
{
"id": 2,
"name": "Spence Durham"
}
],
"greeting": "Hello, Mariana Kane! You have 5 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e09055ff8e3aa87d97",
"index": 77,
"guid": "87b3549d-b517-40e0-a1ab-9ba759d2d49f",
"isActive": false,
"balance": "$2,851.58",
"picture": "http://placehold.it/32x32",
"age": 37,
"eyeColor": "blue",
"name": "Janette Callahan",
"gender": "female",
"company": "DOGNOST",
"email": "janettecallahan@dognost.com",
"phone": "+1 (974) 461-3304",
"address": "304 Heyward Street, Hemlock, Wisconsin, 6129",
"about": "Lorem adipisicing deserunt irure cillum consequat adipisicing qui laboris eiusmod minim. Pariatur sunt proident commodo do elit sint ullamco commodo non dolor mollit ea occaecat labore. Sunt pariatur enim minim elit qui magna voluptate fugiat ut aute irure pariatur proident. Exercitation ipsum occaecat excepteur laborum commodo. Aliquip veniam proident ea nulla laboris eiusmod nostrud elit cupidatat ut eiusmod. Tempor id consectetur dolor sint aute amet non commodo officia. Qui nostrud qui in ut adipisicing nulla Lorem deserunt reprehenderit exercitation.\r\n",
"registered": "2016-04-27T05:33:49 -01:00",
"latitude": 73.670122,
"longitude": 90.836654,
"tags": [
"sunt",
"Lorem",
"deserunt",
"sunt",
"consectetur",
"commodo",
"ipsum"
],
"friends": [
{
"id": 0,
"name": "Johnston Figueroa"
},
{
"id": 1,
"name": "Pollard Meyers"
},
{
"id": 2,
"name": "Bridges Maldonado"
}
],
"greeting": "Hello, Janette Callahan! You have 8 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0b63c098a163b52b6",
"index": 78,
"guid": "f9557ad8-47ce-4a85-b3af-31aa5ff7376c",
"isActive": true,
"balance": "$3,559.34",
"picture": "http://placehold.it/32x32",
"age": 39,
"eyeColor": "blue",
"name": "Shepard Bartlett",
"gender": "male",
"company": "TEMORAK",
"email": "shepardbartlett@temorak.com",
"phone": "+1 (962) 515-3924",
"address": "223 Hinsdale Street, Urbana, Vermont, 9051",
"about": "Enim deserunt aliquip aute aliquip minim eiusmod. Culpa proident anim enim elit magna cupidatat dolore aute consequat est fugiat culpa. Irure qui consectetur magna commodo ad dolor deserunt. Aliquip minim laboris ex et incididunt magna consectetur. Ut irure laborum do ipsum esse enim sit ad sint id pariatur.\r\n",
"registered": "2014-12-21T12:08:35 -00:00",
"latitude": 12.101312,
"longitude": -136.823819,
"tags": [
"dolor",
"fugiat",
"adipisicing",
"veniam",
"laborum",
"exercitation",
"esse"
],
"friends": [
{
"id": 0,
"name": "Burton Dudley"
},
{
"id": 1,
"name": "Queen Herring"
},
{
"id": 2,
"name": "Bridgette Grant"
}
],
"greeting": "Hello, Shepard Bartlett! You have 1 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e01da9b909b65c2f87",
"index": 79,
"guid": "d05a834f-0440-4d1c-aac7-a431d3b0986e",
"isActive": true,
"balance": "$2,452.00",
"picture": "http://placehold.it/32x32",
"age": 20,
"eyeColor": "green",
"name": "Georgina Kim",
"gender": "female",
"company": "GINKLE",
"email": "georginakim@ginkle.com",
"phone": "+1 (922) 519-3015",
"address": "492 Sutton Street, Fairfield, American Samoa, 239",
"about": "Reprehenderit ullamco veniam anim sint enim excepteur laborum magna. Consectetur fugiat officia ipsum tempor magna pariatur velit sunt esse Lorem. Reprehenderit qui culpa aute et tempor dolore cillum laboris reprehenderit ut adipisicing qui eiusmod voluptate. Id magna duis ullamco consequat ad officia ut voluptate.\r\n",
"registered": "2015-06-26T06:05:40 -01:00",
"latitude": 81.496121,
"longitude": -25.543213,
"tags": [
"laborum",
"commodo",
"veniam",
"labore",
"consectetur",
"duis",
"exercitation"
],
"friends": [
{
"id": 0,
"name": "Minnie Harrell"
},
{
"id": 1,
"name": "Lacey Pugh"
},
{
"id": 2,
"name": "Nona Carr"
}
],
"greeting": "Hello, Georgina Kim! You have 4 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e07807ac4add7d7035",
"index": 80,
"guid": "6e033b80-9106-4f9b-9c84-8b9c091a1530",
"isActive": true,
"balance": "$2,696.05",
"picture": "http://placehold.it/32x32",
"age": 28,
"eyeColor": "blue",
"name": "Joy Jacobs",
"gender": "female",
"company": "COSMETEX",
"email": "joyjacobs@cosmetex.com",
"phone": "+1 (876) 599-3813",
"address": "105 Hinckley Place, Draper, Delaware, 6582",
"about": "Id reprehenderit aliquip labore nisi nulla pariatur quis ullamco eu dolore. Anim mollit commodo tempor laborum excepteur aliqua quis pariatur. Enim est adipisicing aliqua sint irure. Pariatur aute aliquip aute veniam. Ea ullamco aute proident laboris. Cupidatat in do dolor consectetur reprehenderit cupidatat labore exercitation consequat nostrud fugiat ullamco enim. Laboris laborum qui ut occaecat est sint voluptate tempor sunt commodo tempor non.\r\n",
"registered": "2015-06-07T05:18:39 -01:00",
"latitude": -75.591255,
"longitude": -131.496234,
"tags": [
"mollit",
"officia",
"voluptate",
"duis",
"veniam",
"voluptate",
"pariatur"
],
"friends": [
{
"id": 0,
"name": "Mathis Reeves"
},
{
"id": 1,
"name": "Hallie Madden"
},
{
"id": 2,
"name": "Knapp Gibbs"
}
],
"greeting": "Hello, Joy Jacobs! You have 10 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e069c962956d751798",
"index": 81,
"guid": "d544ba7f-df18-49ff-8285-3817f922fd0b",
"isActive": true,
"balance": "$1,909.70",
"picture": "http://placehold.it/32x32",
"age": 28,
"eyeColor": "green",
"name": "Sparks Guzman",
"gender": "male",
"company": "QUADEEBO",
"email": "sparksguzman@quadeebo.com",
"phone": "+1 (958) 500-2789",
"address": "601 Wallabout Street, Emison, Oklahoma, 2589",
"about": "Consectetur ad laboris proident Lorem consequat pariatur culpa pariatur. Exercitation labore incididunt adipisicing officia aute velit exercitation sint est duis commodo pariatur elit occaecat. Adipisicing ipsum ullamco duis magna dolore veniam aliquip. Labore anim aute labore dolore dolore nulla. Irure ea Lorem commodo velit veniam veniam excepteur laborum est quis aliqua. Labore in deserunt cupidatat exercitation irure occaecat magna tempor mollit aute amet irure ut qui.\r\n",
"registered": "2015-02-22T12:48:52 -00:00",
"latitude": 31.124862,
"longitude": 158.293069,
"tags": [
"Lorem",
"deserunt",
"dolore",
"sit",
"sunt",
"eiusmod",
"ullamco"
],
"friends": [
{
"id": 0,
"name": "Pace Kidd"
},
{
"id": 1,
"name": "Trisha Leon"
},
{
"id": 2,
"name": "Natalia Chang"
}
],
"greeting": "Hello, Sparks Guzman! You have 4 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0bade8bedd0ff710b",
"index": 82,
"guid": "c0078cee-7042-4b62-84a1-6ed89fe3856b",
"isActive": false,
"balance": "$1,843.36",
"picture": "http://placehold.it/32x32",
"age": 36,
"eyeColor": "blue",
"name": "Laurel Dominguez",
"gender": "female",
"company": "GAZAK",
"email": "laureldominguez@gazak.com",
"phone": "+1 (943) 437-3840",
"address": "889 Sackman Street, Wakarusa, New Mexico, 5762",
"about": "Nisi voluptate nisi commodo reprehenderit eu esse. Proident Lorem veniam cupidatat tempor sit labore exercitation reprehenderit est qui. Laboris consequat pariatur ea laboris ex mollit eu dolor ad cupidatat culpa laboris sit laborum. Enim nulla veniam sint et non minim irure. Laborum in culpa ea sint eu aute ex amet laborum id eu id magna.\r\n",
"registered": "2015-03-12T03:57:34 -00:00",
"latitude": -64.516167,
"longitude": 35.986483,
"tags": [
"eu",
"Lorem",
"ut",
"dolore",
"sint",
"sit",
"id"
],
"friends": [
{
"id": 0,
"name": "Marla Moore"
},
{
"id": 1,
"name": "Ramirez Horn"
},
{
"id": 2,
"name": "Lester Nielsen"
}
],
"greeting": "Hello, Laurel Dominguez! You have 4 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0e95569b35389eb2f",
"index": 83,
"guid": "dcce25ad-251e-4477-9381-4a197ffb7901",
"isActive": true,
"balance": "$3,781.09",
"picture": "http://placehold.it/32x32",
"age": 22,
"eyeColor": "green",
"name": "Cline Lindsay",
"gender": "male",
"company": "SLOGANAUT",
"email": "clinelindsay@sloganaut.com",
"phone": "+1 (970) 532-2378",
"address": "637 Ira Court, Dundee, Texas, 6458",
"about": "Aute duis enim nisi ex sint ea. Non proident proident sint quis mollit non sunt et. Aute irure ex eu ea duis. In laboris culpa cillum incididunt occaecat magna cillum do eu ex aliquip reprehenderit magna magna. Labore aliquip deserunt tempor amet enim ad officia cillum dolore commodo.\r\n",
"registered": "2015-12-28T10:50:19 -00:00",
"latitude": -63.749062,
"longitude": 58.811519,
"tags": [
"amet",
"ut",
"ut",
"nostrud",
"duis",
"eu",
"aliqua"
],
"friends": [
{
"id": 0,
"name": "Dixon Boone"
},
{
"id": 1,
"name": "Annie Chase"
},
{
"id": 2,
"name": "Riley Rocha"
}
],
"greeting": "Hello, Cline Lindsay! You have 2 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0cdd6aea5a38e7b6c",
"index": 84,
"guid": "500562c6-9ba3-430b-87f1-04e122766d3b",
"isActive": false,
"balance": "$1,804.70",
"picture": "http://placehold.it/32x32",
"age": 30,
"eyeColor": "green",
"name": "Margo Mcknight",
"gender": "female",
"company": "EXOZENT",
"email": "margomcknight@exozent.com",
"phone": "+1 (881) 471-2435",
"address": "191 Gerald Court, Whipholt, Washington, 1806",
"about": "Aute incididunt exercitation elit aliqua magna dolore dolore veniam. Ex incididunt anim occaecat ut mollit laborum proident. Ea dolor dolore cupidatat et est culpa sit. Occaecat incididunt et id veniam cillum. Voluptate commodo incididunt enim ut commodo cillum deserunt. Tempor et esse fugiat adipisicing velit duis est excepteur labore adipisicing voluptate ipsum.\r\n",
"registered": "2015-08-21T04:09:30 -01:00",
"latitude": 42.579474,
"longitude": 138.678734,
"tags": [
"esse",
"cupidatat",
"occaecat",
"elit",
"eu",
"ea",
"ut"
],
"friends": [
{
"id": 0,
"name": "Duffy Potter"
},
{
"id": 1,
"name": "Christa Crosby"
},
{
"id": 2,
"name": "Yolanda Case"
}
],
"greeting": "Hello, Margo Mcknight! You have 9 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0f540504c47a4c1f0",
"index": 85,
"guid": "2e7d709f-cf16-446a-a289-621692a50b8c",
"isActive": false,
"balance": "$3,661.99",
"picture": "http://placehold.it/32x32",
"age": 36,
"eyeColor": "blue",
"name": "Jefferson Dennis",
"gender": "male",
"company": "PROWASTE",
"email": "jeffersondennis@prowaste.com",
"phone": "+1 (826) 530-2655",
"address": "566 Sullivan Place, Comptche, Arkansas, 3442",
"about": "Amet voluptate commodo velit incididunt proident et ut. Qui do aliqua occaecat nostrud anim proident esse minim minim adipisicing adipisicing ea aliqua culpa. Eu Lorem tempor laborum est non sint minim quis incididunt.\r\n",
"registered": "2014-04-08T08:31:25 -01:00",
"latitude": -70.641412,
"longitude": 144.987812,
"tags": [
"incididunt",
"dolor",
"amet",
"velit",
"incididunt",
"irure",
"ad"
],
"friends": [
{
"id": 0,
"name": "Mann Wilkerson"
},
{
"id": 1,
"name": "Ella Wyatt"
},
{
"id": 2,
"name": "George Weiss"
}
],
"greeting": "Hello, Jefferson Dennis! You have 3 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e01deefd0fc4eaa4f6",
"index": 86,
"guid": "841b2ef4-6d11-44f4-91ae-a5e59adacd06",
"isActive": false,
"balance": "$1,270.61",
"picture": "http://placehold.it/32x32",
"age": 31,
"eyeColor": "brown",
"name": "Bell Rodriquez",
"gender": "male",
"company": "ZILCH",
"email": "bellrodriquez@zilch.com",
"phone": "+1 (951) 456-2335",
"address": "727 Rose Street, Emory, Virgin Islands, 1552",
"about": "Mollit exercitation velit in aute culpa quis aliqua enim occaecat eu irure. Pariatur enim amet ad ex sunt ea. Id ex exercitation ullamco nisi culpa. Laboris excepteur quis sint aliquip tempor minim adipisicing enim sint est ex. Id duis ex Lorem eiusmod in dolor eiusmod irure esse dolor occaecat sunt. Cupidatat minim pariatur eu eiusmod nisi magna occaecat incididunt culpa est. Sint labore qui ipsum duis.\r\n",
"registered": "2015-12-05T11:02:19 -00:00",
"latitude": -17.603854,
"longitude": 139.917786,
"tags": [
"eu",
"nulla",
"reprehenderit",
"culpa",
"nulla",
"non",
"aliqua"
],
"friends": [
{
"id": 0,
"name": "Lourdes Townsend"
},
{
"id": 1,
"name": "Stella Robles"
},
{
"id": 2,
"name": "Martin Parrish"
}
],
"greeting": "Hello, Bell Rodriquez! You have 10 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0d034b743dbc81e20",
"index": 87,
"guid": "5cfc0a34-a81d-4d3d-8314-f92aedf65482",
"isActive": false,
"balance": "$1,883.38",
"picture": "http://placehold.it/32x32",
"age": 22,
"eyeColor": "blue",
"name": "Freeman Gibson",
"gender": "male",
"company": "ZENTIA",
"email": "freemangibson@zentia.com",
"phone": "+1 (902) 441-3404",
"address": "504 Garland Court, Finzel, Alabama, 4832",
"about": "Sint nulla Lorem do ad magna anim irure officia enim occaecat. Minim elit esse amet id fugiat excepteur deserunt mollit dolore ut cillum culpa in. Culpa sit laborum tempor in tempor.\r\n",
"registered": "2014-12-19T04:24:51 -00:00",
"latitude": -6.469469,
"longitude": 106.886601,
"tags": [
"pariatur",
"laborum",
"commodo",
"mollit",
"cillum",
"excepteur",
"laborum"
],
"friends": [
{
"id": 0,
"name": "Juliana Guthrie"
},
{
"id": 1,
"name": "Graves Mcintosh"
},
{
"id": 2,
"name": "Curtis Quinn"
}
],
"greeting": "Hello, Freeman Gibson! You have 3 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e0aed52ae38dd9c27a",
"index": 88,
"guid": "c74e1948-ad4b-4f5a-a0ed-7d454fd0aebf",
"isActive": false,
"balance": "$2,353.11",
"picture": "http://placehold.it/32x32",
"age": 33,
"eyeColor": "brown",
"name": "Witt Woodward",
"gender": "male",
"company": "UNIWORLD",
"email": "wittwoodward@uniworld.com",
"phone": "+1 (845) 472-2971",
"address": "937 Humboldt Street, Escondida, Maine, 5724",
"about": "Eiusmod cillum ut elit aliquip anim enim adipisicing ipsum dolor irure tempor qui. Do sunt eiusmod sint consequat ipsum in. Reprehenderit sint magna do nostrud reprehenderit elit. Dolore reprehenderit ad deserunt ut aliquip proident amet cillum. Ipsum qui sit tempor dolore sunt sit aliquip anim eu qui commodo.\r\n",
"registered": "2016-08-08T08:31:25 -01:00",
"latitude": -81.60096,
"longitude": -85.686079,
"tags": [
"enim",
"ea",
"adipisicing",
"nisi",
"ea",
"excepteur",
"ut"
],
"friends": [
{
"id": 0,
"name": "Blake Chandler"
},
{
"id": 1,
"name": "Soto Cain"
},
{
"id": 2,
"name": "Wyatt Jones"
}
],
"greeting": "Hello, Witt Woodward! You have 3 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0d01df794ba3c1a97",
"index": 89,
"guid": "55ff70f3-fb15-4ca8-8904-98b6975ec0de",
"isActive": true,
"balance": "$2,552.79",
"picture": "http://placehold.it/32x32",
"age": 40,
"eyeColor": "blue",
"name": "Lee Baird",
"gender": "female",
"company": "IMANT",
"email": "leebaird@imant.com",
"phone": "+1 (905) 516-3570",
"address": "904 Lawn Court, Blanford, Arizona, 6051",
"about": "Labore excepteur commodo magna aliquip laboris dolore incididunt et id consequat veniam. Consectetur minim occaecat est qui adipisicing ut dolore laboris non et amet ipsum tempor. Ex ipsum id labore sit pariatur excepteur consequat consequat officia anim aliqua occaecat. Sint ipsum enim incididunt tempor enim minim dolor ex. Cillum eu veniam ullamco laboris nisi. Est veniam incididunt cupidatat enim est. Sit Lorem eiusmod aute adipisicing est eu aliquip esse nostrud irure.\r\n",
"registered": "2015-05-18T03:24:48 -01:00",
"latitude": -75.082952,
"longitude": 41.68256,
"tags": [
"in",
"est",
"irure",
"ea",
"esse",
"laborum",
"ad"
],
"friends": [
{
"id": 0,
"name": "Alejandra Reilly"
},
{
"id": 1,
"name": "Amalia Valencia"
},
{
"id": 2,
"name": "Imogene Craig"
}
],
"greeting": "Hello, Lee Baird! You have 4 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e095c831fa7a4083cf",
"index": 90,
"guid": "85993d2f-11e2-433b-9b0c-7c08a68f3ef6",
"isActive": true,
"balance": "$1,559.64",
"picture": "http://placehold.it/32x32",
"age": 29,
"eyeColor": "brown",
"name": "Puckett Manning",
"gender": "male",
"company": "COREPAN",
"email": "puckettmanning@corepan.com",
"phone": "+1 (870) 485-2679",
"address": "145 Miami Court, Dorneyville, North Dakota, 9769",
"about": "Tempor aute nisi est ex. Eu consectetur cupidatat ullamco nostrud proident ea eiusmod quis duis mollit consequat magna. Ut in id laborum enim. Laborum mollit quis aute et in eu cupidatat tempor et. Irure commodo aute sint voluptate anim mollit magna. Dolore laboris esse nisi in nisi eiusmod do culpa pariatur proident nisi. Pariatur sit magna et tempor sunt ea aute dolore proident sunt qui esse eiusmod eu.\r\n",
"registered": "2014-03-27T01:48:45 -00:00",
"latitude": -5.929811,
"longitude": 68.330907,
"tags": [
"aliquip",
"non",
"ex",
"id",
"ut",
"amet",
"eiusmod"
],
"friends": [
{
"id": 0,
"name": "Erin Stephenson"
},
{
"id": 1,
"name": "Maryanne Solis"
},
{
"id": 2,
"name": "Parker Mack"
}
],
"greeting": "Hello, Puckett Manning! You have 4 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e097f3fdf83eed909b",
"index": 91,
"guid": "324de3e3-125f-4a64-bc9f-24440d2f9c1e",
"isActive": true,
"balance": "$1,857.20",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "green",
"name": "Ines Hoover",
"gender": "female",
"company": "ZAYA",
"email": "ineshoover@zaya.com",
"phone": "+1 (967) 598-2124",
"address": "871 Tilden Avenue, Catharine, South Carolina, 4736",
"about": "Cupidatat laboris aliquip non veniam ullamco culpa proident eu in ex ad. Minim Lorem dolor magna eiusmod eiusmod ut irure. Cillum ut officia ullamco voluptate Lorem ea reprehenderit exercitation excepteur ad. Aliqua ut fugiat labore dolor tempor pariatur aliqua Lorem fugiat. Consequat qui elit aliquip do et ea mollit dolore esse.\r\n",
"registered": "2015-03-21T02:39:19 -00:00",
"latitude": 16.339212,
"longitude": 110.751185,
"tags": [
"dolore",
"elit",
"officia",
"ullamco",
"aliquip",
"laborum",
"incididunt"
],
"friends": [
{
"id": 0,
"name": "Eloise Golden"
},
{
"id": 1,
"name": "Harrell Waller"
},
{
"id": 2,
"name": "Leanna Hester"
}
],
"greeting": "Hello, Ines Hoover! You have 10 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "57d068e0436800105ab6808b",
"index": 92,
"guid": "f8926032-a374-4495-9f34-8625a1a60af4",
"isActive": false,
"balance": "$2,800.72",
"picture": "http://placehold.it/32x32",
"age": 25,
"eyeColor": "brown",
"name": "Meagan Scott",
"gender": "female",
"company": "SUREPLEX",
"email": "meaganscott@sureplex.com",
"phone": "+1 (932) 516-3092",
"address": "171 Newport Street, Whitestone, Puerto Rico, 3865",
"about": "Ipsum aliquip proident anim in ut cupidatat et elit commodo aute commodo aliquip. Dolor aliqua voluptate laborum eiusmod fugiat non minim ad cupidatat sint sunt dolore quis. Id ad voluptate non non eiusmod eiusmod cupidatat minim eu consequat occaecat nostrud. Incididunt laborum eiusmod ullamco duis exercitation. Deserunt consectetur ad nulla enim sit reprehenderit incididunt adipisicing minim magna officia aliqua aliquip labore.\r\n",
"registered": "2014-03-26T10:14:45 -00:00",
"latitude": 49.970535,
"longitude": -58.076613,
"tags": [
"incididunt",
"do",
"ullamco",
"sit",
"eu",
"ea",
"est"
],
"friends": [
{
"id": 0,
"name": "Castillo House"
},
{
"id": 1,
"name": "Carey Harris"
},
{
"id": 2,
"name": "Delacruz Lopez"
}
],
"greeting": "Hello, Meagan Scott! You have 9 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0a44801556c71de73",
"index": 93,
"guid": "44dc7f0e-e206-46b1-a411-8550cce7e0be",
"isActive": false,
"balance": "$2,885.30",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "brown",
"name": "Peck Mathis",
"gender": "male",
"company": "LIQUICOM",
"email": "peckmathis@liquicom.com",
"phone": "+1 (807) 575-2633",
"address": "735 Halleck Street, Shindler, Maryland, 1336",
"about": "Ipsum duis dolore et cillum cupidatat duis labore fugiat nostrud. Qui cillum cillum cillum irure mollit laboris reprehenderit dolor est ut sunt excepteur et. Ad commodo excepteur cillum elit exercitation. Eiusmod laboris eiusmod ad nulla aliqua occaecat aute ex do nisi. Qui elit aliqua officia deserunt quis magna.\r\n",
"registered": "2015-12-17T03:19:16 -00:00",
"latitude": 36.272445,
"longitude": -37.016525,
"tags": [
"commodo",
"id",
"aute",
"ad",
"voluptate",
"aute",
"cillum"
],
"friends": [
{
"id": 0,
"name": "Camille Bentley"
},
{
"id": 1,
"name": "Gladys Clemons"
},
{
"id": 2,
"name": "Rivers Juarez"
}
],
"greeting": "Hello, Peck Mathis! You have 4 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "57d068e04584df26d2f2615d",
"index": 94,
"guid": "2c899541-146a-44d7-a97d-b692114db7d2",
"isActive": true,
"balance": "$1,813.09",
"picture": "http://placehold.it/32x32",
"age": 35,
"eyeColor": "green",
"name": "Adele Donovan",
"gender": "female",
"company": "CORIANDER",
"email": "adeledonovan@coriander.com",
"phone": "+1 (953) 528-3860",
"address": "941 Brighton Avenue, Cade, California, 5654",
"about": "Non quis cillum laboris velit incididunt aliquip pariatur. Velit dolore consequat veniam irure. Aliqua veniam sunt commodo ex elit anim est tempor laboris proident.\r\n",
"registered": "2016-08-25T05:07:37 -01:00",
"latitude": -63.415124,
"longitude": 111.307023,
"tags": [
"proident",
"cupidatat",
"anim",
"sint",
"fugiat",
"occaecat",
"ad"
],
"friends": [
{
"id": 0,
"name": "Francisca Shaw"
},
{
"id": 1,
"name": "Ruth Savage"
},
{
"id": 2,
"name": "Jasmine Barlow"
}
],
"greeting": "Hello, Adele Donovan! You have 8 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "57d068e0c209bce394a1d6b8",
"index": 95,
"guid": "d7d4a938-4849-40ad-8059-ec61f58a84ff",
"isActive": true,
"balance": "$3,399.11",
"picture": "http://placehold.it/32x32",
"age": 23,
"eyeColor": "brown"
gitextract_i63kwxl_/ ├── .github/ │ └── workflows/ │ ├── build.yml │ └── release.yml ├── .gitignore ├── .goreleaser.yml ├── .travis.yml ├── ADVANCED.mkd ├── CHANGELOG.mkd ├── CONTRIBUTING.mkd ├── LICENSE ├── README.mkd ├── completions/ │ ├── gron.bash │ └── gron.fish ├── docs/ │ └── index.html ├── go.mod ├── go.sum ├── identifier.go ├── identifier_test.go ├── main.go ├── main_test.go ├── original-gron.php ├── script/ │ ├── example │ ├── lint │ ├── precommit │ ├── profile │ ├── release │ └── test ├── statements.go ├── statements_test.go ├── testdata/ │ ├── big.json │ ├── github.gron │ ├── github.jgron │ ├── github.json │ ├── grep-separators.gron │ ├── grep-separators.json │ ├── invalid-type-mismatch.gron │ ├── invalid-value.gron │ ├── large-line.gron │ ├── large-line.json │ ├── long-stream.gron │ ├── long-stream.json │ ├── one.gron │ ├── one.jgron │ ├── one.json │ ├── scalar-stream.gron │ ├── scalar-stream.jgron │ ├── scalar-stream.json │ ├── stream.gron │ ├── stream.jgron │ ├── stream.json │ ├── three.gron │ ├── three.jgron │ ├── three.json │ ├── two-b.json │ ├── two.gron │ ├── two.jgron │ └── two.json ├── token.go ├── token_test.go ├── ungron.go ├── ungron_test.go ├── url.go └── url_test.go
SYMBOL INDEX (137 symbols across 13 files)
FILE: identifier.go
function validIdentifier (line 52) | func validIdentifier(s string) bool {
function validFirstRune (line 75) | func validFirstRune(r rune) bool {
function validSecondaryRune (line 87) | func validSecondaryRune(r rune) bool {
FILE: identifier_test.go
function TestValidIdentifier (line 5) | func TestValidIdentifier(t *testing.T) {
function TestValidFirstRune (line 37) | func TestValidFirstRune(t *testing.T) {
function TestValidSecondaryRune (line 56) | func TestValidSecondaryRune(t *testing.T) {
function BenchmarkValidIdentifier (line 75) | func BenchmarkValidIdentifier(b *testing.B) {
function BenchmarkValidIdentifierUnquoted (line 81) | func BenchmarkValidIdentifierUnquoted(b *testing.B) {
function BenchmarkValidIdentifierReserved (line 87) | func BenchmarkValidIdentifierReserved(b *testing.B) {
FILE: main.go
constant exitOK (line 22) | exitOK = iota
constant exitOpenFile (line 23) | exitOpenFile
constant exitReadInput (line 24) | exitReadInput
constant exitFormStatements (line 25) | exitFormStatements
constant exitFetchURL (line 26) | exitFetchURL
constant exitParseStatements (line 27) | exitParseStatements
constant exitJSONEncode (line 28) | exitJSONEncode
constant optMonochrome (line 33) | optMonochrome = 1 << iota
constant optNoSort (line 34) | optNoSort
constant optJSON (line 35) | optJSON
function init (line 56) | func init() {
function main (line 96) | func main() {
type actionFn (line 202) | type actionFn
function gron (line 206) | func gron(r io.Reader, w io.Writer, opts int) (int, error) {
function gronStream (line 247) | func gronStream(r io.Reader, w io.Writer, opts int) (int, error) {
function ungron (line 336) | func ungron(r io.Reader, w io.Writer, opts int) (int, error) {
function gronValues (line 416) | func gronValues(r io.Reader, w io.Writer, opts int) (int, error) {
function colorizeJSON (line 459) | func colorizeJSON(src []byte) ([]byte, error) {
function fatal (line 479) | func fatal(code int, err error) {
FILE: main_test.go
function TestGron (line 12) | func TestGron(t *testing.T) {
function TestGronStream (line 53) | func TestGronStream(t *testing.T) {
function TestLargeGronStream (line 92) | func TestLargeGronStream(t *testing.T) {
function TestUngron (line 130) | func TestUngron(t *testing.T) {
function TestGronJ (line 185) | func TestGronJ(t *testing.T) {
function TestGronStreamJ (line 226) | func TestGronStreamJ(t *testing.T) {
function TestUngronJ (line 265) | func TestUngronJ(t *testing.T) {
function BenchmarkBigJSON (line 318) | func BenchmarkBigJSON(b *testing.B) {
FILE: original-gron.php
function printSruct (line 81) | function printSruct($struct, $prefix = 'json'){
FILE: statements.go
type statement (line 22) | type statement
method String (line 26) | func (s statement) String() string {
method colorString (line 35) | func (s statement) colorString() string {
method withBare (line 58) | func (s statement) withBare(k string) statement {
method jsonify (line 69) | func (s statement) jsonify() (statement, error) {
method withQuotedKey (line 107) | func (s statement) withQuotedKey(k string) statement {
method withNumericKey (line 120) | func (s statement) withNumericKey(k int) statement {
type statementconv (line 44) | type statementconv
function statementToString (line 47) | func statementToString(s statement) string {
function statementToColorString (line 52) | func statementToColorString(s statement) string {
type statements (line 133) | type statements
method addWithValue (line 138) | func (ss *statements) addWithValue(path statement, value token) {
method add (line 146) | func (ss *statements) add(s statement) {
method Len (line 151) | func (ss statements) Len() int {
method Swap (line 156) | func (ss statements) Swap(i, j int) {
method toInterface (line 275) | func (ss statements) toInterface() (interface{}, error) {
method Less (line 312) | func (ss statements) Less(a, b int) bool {
method Contains (line 377) | func (ss statements) Contains(search statement) bool {
method fill (line 403) | func (ss *statements) fill(prefix statement, v interface{}) {
type statementmaker (line 162) | type statementmaker
function statementFromString (line 166) | func statementFromString(str string) statement {
function statementFromStringMaker (line 173) | func statementFromStringMaker(str string) (statement, error) {
function statementFromJSONSpec (line 179) | func statementFromJSONSpec(str string) (statement, error) {
function statementsFromJSON (line 388) | func statementsFromJSON(r io.Reader, prefix statement) (statements, erro...
FILE: statements_test.go
function statementsFromStringSlice (line 11) | func statementsFromStringSlice(strs []string) statements {
function TestStatementsSimple (line 19) | func TestStatementsSimple(t *testing.T) {
function TestStatementsSorting (line 68) | func TestStatementsSorting(t *testing.T) {
function BenchmarkStatementsLess (line 100) | func BenchmarkStatementsLess(b *testing.B) {
function BenchmarkFill (line 111) | func BenchmarkFill(b *testing.B) {
function TestUngronStatementsSimple (line 137) | func TestUngronStatementsSimple(t *testing.T) {
function TestUngronStatementsInvalid (line 174) | func TestUngronStatementsInvalid(t *testing.T) {
function TestStatement (line 189) | func TestStatement(t *testing.T) {
FILE: token.go
type token (line 11) | type token struct
method isValue (line 73) | func (t token) isValue() bool {
method isPunct (line 83) | func (t token) isPunct() bool {
method format (line 93) | func (t token) format() string {
method formatColor (line 101) | func (t token) formatColor() string {
type tokenTyp (line 17) | type tokenTyp
constant typBare (line 21) | typBare tokenTyp = iota
constant typNumericKey (line 24) | typNumericKey
constant typQuotedKey (line 27) | typQuotedKey
constant typDot (line 30) | typDot
constant typLBrace (line 31) | typLBrace
constant typRBrace (line 32) | typRBrace
constant typEquals (line 33) | typEquals
constant typSemi (line 34) | typSemi
constant typComma (line 35) | typComma
constant typString (line 38) | typString
constant typNumber (line 39) | typNumber
constant typTrue (line 40) | typTrue
constant typFalse (line 41) | typFalse
constant typNull (line 42) | typNull
constant typEmptyArray (line 43) | typEmptyArray
constant typEmptyObject (line 44) | typEmptyObject
constant typIgnored (line 47) | typIgnored
constant typError (line 50) | typError
type sprintFn (line 54) | type sprintFn
function valueTokenFromInterface (line 116) | func valueTokenFromInterface(v interface{}) token {
function quoteString (line 141) | func quoteString(s string) string {
FILE: token_test.go
function TestValueTokenFromInterface (line 31) | func TestValueTokenFromInterface(t *testing.T) {
function BenchmarkValueTokenFromInterface (line 45) | func BenchmarkValueTokenFromInterface(b *testing.B) {
FILE: ungron.go
type errRecoverable (line 29) | type errRecoverable struct
method Error (line 33) | func (e errRecoverable) Error() string {
type lexer (line 38) | type lexer struct
method lex (line 59) | func (l *lexer) lex() statement {
method next (line 68) | func (l *lexer) next() rune {
method backup (line 82) | func (l *lexer) backup() {
method peek (line 88) | func (l *lexer) peek() rune {
method ignore (line 95) | func (l *lexer) ignore() {
method emit (line 101) | func (l *lexer) emit(typ tokenTyp) {
method accept (line 113) | func (l *lexer) accept(valid string) bool {
method acceptRun (line 123) | func (l *lexer) acceptRun(valid string) {
method acceptFunc (line 135) | func (l *lexer) acceptFunc(fn runeCheck) bool {
method acceptRunFunc (line 145) | func (l *lexer) acceptRunFunc(fn runeCheck) {
method acceptUntil (line 153) | func (l *lexer) acceptUntil(delims string) {
method acceptUntilUnescaped (line 165) | func (l *lexer) acceptUntilUnescaped(delims string) {
function newLexer (line 49) | func newLexer(text string) *lexer {
type runeCheck (line 131) | type runeCheck
type lexFn (line 188) | type lexFn
function lexStatement (line 192) | func lexStatement(l *lexer) lexFn {
function lexBareWord (line 218) | func lexBareWord(l *lexer) lexFn {
function lexBraces (line 234) | func lexBraces(l *lexer) lexFn {
function lexNumericKey (line 250) | func lexNumericKey(l *lexer) lexFn {
function lexQuotedKey (line 268) | func lexQuotedKey(l *lexer) lexFn {
function lexValue (line 289) | func lexValue(l *lexer) lexFn {
function lexIgnore (line 348) | func lexIgnore(l *lexer) lexFn {
function ungronTokens (line 357) | func ungronTokens(ts []token) (interface{}, error) {
function recursiveMerge (line 443) | func recursiveMerge(a, b interface{}) (interface{}, error) {
function recursiveMapMerge (line 470) | func recursiveMapMerge(a, b map[string]interface{}) (map[string]interfac...
function recursiveSliceMerge (line 491) | func recursiveSliceMerge(a, b []interface{}) ([]interface{}, error) {
FILE: ungron_test.go
function TestLex (line 8) | func TestLex(t *testing.T) {
function TestUngronTokensSimple (line 194) | func TestUngronTokensSimple(t *testing.T) {
function TestUngronTokensInvalid (line 223) | func TestUngronTokensInvalid(t *testing.T) {
function TestMerge (line 242) | func TestMerge(t *testing.T) {
FILE: url.go
function validURL (line 16) | func validURL(url string) bool {
function configureProxy (line 21) | func configureProxy(url string, proxy string, noProxy string) func(*http...
function getURL (line 69) | func getURL(url string, insecure bool, proxyURL string, noProxy string) ...
FILE: url_test.go
function TestValidURL (line 8) | func TestValidURL(t *testing.T) {
function TestConfigureProxyHttp (line 28) | func TestConfigureProxyHttp(t *testing.T) {
function TestConfigureProxyHttps (line 75) | func TestConfigureProxyHttps(t *testing.T) {
Condensed preview — 62 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,550K chars).
[
{
"path": ".github/workflows/build.yml",
"chars": 527,
"preview": "name: Go\non:\n push:\n branches:\n - master\n pull_request:\n workflow_dispatch:\njobs:\n\n build:\n strategy:\n "
},
{
"path": ".github/workflows/release.yml",
"chars": 574,
"preview": "name: release\non:\n push:\n tags:\n - \"*\"\njobs:\n goreleaser:\n runs-on: ubuntu-latest\n steps:\n - name: Ch"
},
{
"path": ".gitignore",
"chars": 54,
"preview": "gron\n*.tgz\n*.zip\n*.swp\n*.exe\ncpu.out\ngron.test\nvendor\n"
},
{
"path": ".goreleaser.yml",
"chars": 114,
"preview": "version: 2\n\nbefore:\n hooks:\n - go mod tidy\n - go mod vendor\n\nsource:\n enabled: true\n files:\n - vendor\n"
},
{
"path": ".travis.yml",
"chars": 147,
"preview": "language: go\n\ngo:\n - \"1.13\"\n - \"1.14\"\n - \"1.15\"\n - \"1.16\"\n - \"1.17\"\n - \"1.18\"\n - \"1.19\"\n - \"1.20\"\n - \"1.21\"\n -"
},
{
"path": "ADVANCED.mkd",
"chars": 5887,
"preview": "# Advanced Usage\n\nAlthough gron's primary purpose is API discovery, when combined with other tools like `grep` it can do"
},
{
"path": "CHANGELOG.mkd",
"chars": 2696,
"preview": "# Changelog\n\n## 0.6.0\n- Adds `--json`/JSON stream output support (thanks @csabahenk!)\n- Removes trailing newline charact"
},
{
"path": "CONTRIBUTING.mkd",
"chars": 460,
"preview": "# Contributing\n\n* Raise an issue if appropriate\n* Fork the repo\n* Make your changes\n* Use [gofmt](https://golang.org/cmd"
},
{
"path": "LICENSE",
"chars": 1067,
"preview": "MIT License\n\nCopyright (c) 2016 Tom Hudson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
},
{
"path": "README.mkd",
"chars": 6801,
"preview": "# gron\n[](https://travis-ci.org/tomnomnom/gron)\n\n"
},
{
"path": "completions/gron.bash",
"chars": 547,
"preview": "#!/usr/bin/env bash\n\n# Bash shell commandline completions for gron.\n#\n# Copy the contents of this file into your ~/.bash"
},
{
"path": "completions/gron.fish",
"chars": 853,
"preview": "#!/usr/bin/env fish\n\n# Fish shell commandline completions for gron.\n#\n# Stick this file in your ~/.config/fish/completio"
},
{
"path": "docs/index.html",
"chars": 1255,
"preview": "<!doctype html>\n<html lang=\"en\">\n <head>\n <title>gron</title>\n <meta http-equiv=\"Content-Type\" content=\"text/"
},
{
"path": "go.mod",
"chars": 292,
"preview": "module github.com/tomnomnom/gron\n\ngo 1.24\n\nrequire (\n\tgithub.com/fatih/color v1.18.0\n\tgithub.com/mattn/go-colorable v0.1"
},
{
"path": "go.sum",
"chars": 1655,
"preview": "github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=\ngithub.com/fatih/color v1.18.0 h1:S"
},
{
"path": "identifier.go",
"chars": 1884,
"preview": "package main\n\nimport \"unicode\"\n\n// The javascript reserved words cannot be used as unquoted keys\nvar reservedWords = map"
},
{
"path": "identifier_test.go",
"chars": 1650,
"preview": "package main\n\nimport \"testing\"\n\nfunc TestValidIdentifier(t *testing.T) {\n\ttests := []struct {\n\t\tkey string\n\t\twant bool\n"
},
{
"path": "main.go",
"chars": 12301,
"preview": "package main\n\nimport (\n\t\"bufio\"\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\t\"sort\"\n\t\"strings\"\n\n\t\"github.com/fa"
},
{
"path": "main_test.go",
"chars": 7480,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"io/ioutil\"\n\t\"os\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestGron(t *testing.T)"
},
{
"path": "original-gron.php",
"chars": 2283,
"preview": "#!/usr/bin/env php\n<?php\n//////////\n// Gron //\n//////////\n\n// Take valid JSON on stdin, or read it from a file or URL,\n/"
},
{
"path": "script/example",
"chars": 93,
"preview": "#!/bin/sh\nPROJDIR=$(cd `dirname $0`/.. && pwd)\ncd $PROJDIR\ngo build\n./gron testdata/one.json\n"
},
{
"path": "script/lint",
"chars": 638,
"preview": "#!/bin/sh\nPROJDIR=$(cd `dirname $0`/.. && pwd)\ncd ${PROJDIR}\n\nwhich gometalinter > /dev/null\n\nif [ $? -ne 0 ]; then\n "
},
{
"path": "script/precommit",
"chars": 83,
"preview": "#!/bin/sh\nset -e\nPROJDIR=$(cd `dirname $0`/.. && pwd)\ncd ${PROJDIR}\n\n./script/test\n"
},
{
"path": "script/profile",
"chars": 205,
"preview": "#!/bin/sh\nset -e\nPROJDIR=$(cd `dirname $0`/.. && pwd)\ncd ${PROJDIR}\n\nPAT=\".\"\nif [ ! -z \"${1}\" ]; then\n PAT=\"${1}\"\nfi\n"
},
{
"path": "script/release",
"chars": 1351,
"preview": "#!/bin/bash\nPROJDIR=$(cd `dirname $0`/.. && pwd)\n\nVERSION=\"${1}\"\nTAG=\"v${VERSION}\"\nUSER=\"tomnomnom\"\nREPO=\"gron\"\nBINARY=\""
},
{
"path": "script/test",
"chars": 70,
"preview": "#!/bin/sh\nPROJDIR=$(cd `dirname $0`/.. && pwd)\ncd ${PROJDIR}\n\ngo test\n"
},
{
"path": "statements.go",
"chars": 10224,
"preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"io\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"strings\"\n\n\t\"github.com/pkg/errors\"\n)\n\n// A "
},
{
"path": "statements_test.go",
"chars": 4196,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"reflect\"\n\t\"sort\"\n\t\"testing\"\n)\n\nfunc statementsFromStringSlice(strs []"
},
{
"path": "testdata/big.json",
"chars": 866302,
"preview": "[\n {\n \"_id\": \"57d068e074bf05b8a0905846\",\n \"index\": 0,\n \"guid\": \"45c7a641-b187-45a6-b1e5-dbd5dd00d88e\",\n \"is"
},
{
"path": "testdata/github.gron",
"chars": 4004,
"preview": "json = [];\njson[0] = {};\njson[0].author = {};\njson[0].author.avatar_url = \"https://avatars.githubusercontent.com/u/58276"
},
{
"path": "testdata/github.jgron",
"chars": 3930,
"preview": "[[],[]]\n[[0],{}]\n[[0,\"author\"],{}]\n[[0,\"author\",\"avatar_url\"],\"https://avatars.githubusercontent.com/u/58276?v=3\"]\n[[0,\""
},
{
"path": "testdata/github.json",
"chars": 3481,
"preview": "[\n {\n \"sha\": \"cfade78b10e9c0cb9e4e0a902f5383ee4e5efc9e\",\n \"commit\": {\n \"author\": {\n \"name\": \"Tom Huds"
},
{
"path": "testdata/grep-separators.gron",
"chars": 126,
"preview": "json.contact.email = \"mail@tomnomnom.com\";\njson.contact.twitter = \"@TomNomNom\";\n--\njson.likes[2] = \"meat\";\njson.name = \""
},
{
"path": "testdata/grep-separators.json",
"chars": 155,
"preview": "{\n \"contact\": {\n \"email\": \"mail@tomnomnom.com\",\n \"twitter\": \"@TomNomNom\"\n },\n \"likes\": [\n null,\n null,\n"
},
{
"path": "testdata/invalid-type-mismatch.gron",
"chars": 30,
"preview": "json.foo = {};\njson.foo = [];\n"
},
{
"path": "testdata/invalid-value.gron",
"chars": 266,
"preview": "json = {};\njson.contact = {};\njson.contact.email = \"mail@tomnomnom.com\";\njson.contact.twitter = \"@TomNomNom\";\njson.githu"
},
{
"path": "testdata/large-line.gron",
"chars": 100027,
"preview": "json = {};\njson.blob = \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"path": "testdata/large-line.json",
"chars": 100012,
"preview": "{\"blob\":\"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"path": "testdata/long-stream.gron",
"chars": 176971,
"preview": "json = [];\njson[0] = {};\njson[0].details = [];\njson[0].details[0] = {};\njson[0].details[0]._id = \"5ae0aa34b3f979b9b85509"
},
{
"path": "testdata/long-stream.json",
"chars": 69588,
"preview": "{\"details\":[{\"_id\":\"5ae0aa34b3f979b9b85509e0\",\"index\":0,\"guid\":\"164542db-58d9-4d63-aacd-fbf3a7739474\",\"isActive\":true,\"b"
},
{
"path": "testdata/one.gron",
"chars": 384,
"preview": "json = {};\njson.abool = true;\njson.abool2 = false;\njson.five = {};\njson.five.alpha = [];\njson.five.alpha[0] = \"fo\";\njson"
},
{
"path": "testdata/one.jgron",
"chars": 348,
"preview": "[[],{}]\n[[\"abool\"],true]\n[[\"abool2\"],false]\n[[\"five\"],{}]\n[[\"five\",\"alpha\"],[]]\n[[\"five\",\"alpha\",0],\"fo\"]\n[[\"five\",\"alph"
},
{
"path": "testdata/one.json",
"chars": 234,
"preview": "{\n \"one\": 1,\n \"two\": 2.2,\n \"three-b\": \"3\",\n \"four\": [1,2,3,4],\n \"five\": {\n \"alpha\": [\"fo\", \"fum\"],\n \"beta\": {"
},
{
"path": "testdata/scalar-stream.gron",
"chars": 107,
"preview": "json = [];\njson[0] = true;\njson[1] = false;\njson[2] = null;\njson[3] = \"hello\";\njson[4] = 4;\njson[5] = 4.4;\n"
},
{
"path": "testdata/scalar-stream.jgron",
"chars": 74,
"preview": "[[],[]]\n[[0],true]\n[[1],false]\n[[2],null]\n[[3],\"hello\"]\n[[4],4]\n[[5],4.4]\n"
},
{
"path": "testdata/scalar-stream.json",
"chars": 30,
"preview": "true\nfalse\nnull\n\"hello\"\n4\n4.4\n"
},
{
"path": "testdata/stream.gron",
"chars": 279,
"preview": "json = [];\njson[0] = {};\njson[0].one = 1;\njson[0].three = [];\njson[0].three[0] = 1;\njson[0].three[1] = 2;\njson[0].three["
},
{
"path": "testdata/stream.jgron",
"chars": 224,
"preview": "[[],[]]\n[[0],{}]\n[[0,\"one\"],1]\n[[0,\"three\"],[]]\n[[0,\"three\",0],1]\n[[0,\"three\",1],2]\n[[0,\"three\",2],3]\n[[0,\"two\"],2]\n[[1]"
},
{
"path": "testdata/stream.json",
"chars": 82,
"preview": "{\"one\": 1, \"two\": 2, \"three\": [1, 2, 3]}\n{\"one\": 1, \"two\": 2, \"three\": [1, 2, 3]}\n"
},
{
"path": "testdata/three.gron",
"chars": 573,
"preview": "json = {};\njson.abool = true;\njson.abool2 = false;\njson.five = {};\njson.five.alpha = [];\njson.five.alpha[0] = \"fo\";\njson"
},
{
"path": "testdata/three.jgron",
"chars": 507,
"preview": "[[],{}]\n[[\"abool\"],true]\n[[\"abool2\"],false]\n[[\"five\"],{}]\n[[\"five\",\"alpha\"],[]]\n[[\"five\",\"alpha\",0],\"fo\"]\n[[\"five\",\"alph"
},
{
"path": "testdata/three.json",
"chars": 259,
"preview": "{\n \"one\": 1,\n \"two\": 2.2,\n \"three-b\": \"3\",\n \"four\": [1,2,3,4,5,6,7,8,9,10,11,12,13,14],\n \"five\": {\n \"alpha\": [\"f"
},
{
"path": "testdata/two-b.json",
"chars": 208,
"preview": "{\n \"name\": \"Tom\",\n \"github\": \"https://github.com/tomnomnom/\",\n \"likes\": [\"code\", \"cheese\", \"meat\"],\n \"contac"
},
{
"path": "testdata/two.gron",
"chars": 267,
"preview": "json = {};\njson.contact = {};\njson.contact.email = \"mail@tomnomnom.com\";\njson.contact.twitter = \"@TomNomNom\";\njson.githu"
},
{
"path": "testdata/two.jgron",
"chars": 247,
"preview": "[[],{}]\n[[\"contact\"],{}]\n[[\"contact\",\"email\"],\"mail@tomnomnom.com\"]\n[[\"contact\",\"twitter\"],\"@TomNomNom\"]\n[[\"github\"],\"ht"
},
{
"path": "testdata/two.json",
"chars": 205,
"preview": "{\n \"name\": \"Tom\",\n \"github\": \"https://github.com/tomnomnom/\",\n \"likes\": [\"code\", \"cheese\", \"meat\"],\n \"contac"
},
{
"path": "token.go",
"chars": 4240,
"preview": "package main\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"unicode\"\n)\n\n// A token is a chunk of text from a statement wit"
},
{
"path": "token_test.go",
"chars": 1220,
"preview": "package main\n\nimport (\n\t\"encoding/json\"\n\t\"testing\"\n)\n\nvar cases = []struct {\n\tin interface{}\n\twant token\n}{\n\t{make(map"
},
{
"path": "ungron.go",
"chars": 11245,
"preview": "// Ungronning is the reverse of gronning: turn statements\n// back into JSON. The expected input grammar is:\n//\n// Inpu"
},
{
"path": "ungron_test.go",
"chars": 5735,
"preview": "package main\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestLex(t *testing.T) {\n\tcases := []struct {\n\t\tin string\n\t\twant ["
},
{
"path": "url.go",
"chars": 2180,
"preview": "package main\n\nimport (\n\t\"bufio\"\n\t\"crypto/tls\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\tneturl \"net/url\"\n\t\"os\"\n\t\"regexp\"\n\t\"strings\"\n\t\"ti"
},
{
"path": "url_test.go",
"chars": 5329,
"preview": "package main\n\nimport (\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestValidURL(t *testing.T) {\n\ttests := []struct {\n\t\turl string\n\t\twant b"
}
]
About this extraction
This page contains the full source code of the tomnomnom/gron GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 62 files (1.4 MB), approximately 424.3k tokens, and a symbol index with 137 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.