{"id":18733270,"url":"https://github.com/autom8ter/myjson","last_synced_at":"2026-03-07T19:33:26.200Z","repository":{"id":65163529,"uuid":"542175788","full_name":"autom8ter/myjson","owner":"autom8ter","description":"MyJSON is an embedded relational document store built on top of pluggable key value storage","archived":false,"fork":false,"pushed_at":"2023-02-09T06:02:44.000Z","size":527,"stargazers_count":14,"open_issues_count":3,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-12T18:46:35.693Z","etag":null,"topics":["database","embedded-database","go","golang","json"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/autom8ter.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-27T16:09:50.000Z","updated_at":"2025-03-19T14:29:55.000Z","dependencies_parsed_at":"2023-02-19T15:00:32.057Z","dependency_job_id":null,"html_url":"https://github.com/autom8ter/myjson","commit_stats":null,"previous_names":["autom8ter/gokvkit"],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/autom8ter/myjson","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autom8ter%2Fmyjson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autom8ter%2Fmyjson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autom8ter%2Fmyjson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autom8ter%2Fmyjson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/autom8ter","download_url":"https://codeload.github.com/autom8ter/myjson/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/autom8ter%2Fmyjson/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30227853,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T19:01:10.287Z","status":"ssl_error","status_checked_at":"2026-03-07T18:59:58.103Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","embedded-database","go","golang","json"],"created_at":"2024-11-07T15:09:14.297Z","updated_at":"2026-03-07T19:33:26.184Z","avatar_url":"https://github.com/autom8ter.png","language":"Go","readme":"# myjson [![GoDoc](https://godoc.org/github.com/autom8ter/myjson?status.svg)](https://godoc.org/github.com/autom8ter/myjson)\n![Coverage](https://img.shields.io/badge/Coverage-72.5%25-brightgreen)\n\n```\n███    ███ ██    ██      ██ ███████  ██████  ███    ██ \n████  ████  ██  ██       ██ ██      ██    ██ ████   ██ \n██ ████ ██   ████        ██ ███████ ██    ██ ██ ██  ██ \n██  ██  ██    ██    ██   ██      ██ ██    ██ ██  ██ ██ \n██      ██    ██     █████  ███████  ██████  ██   ████ \n                                                       \n```\n\nMyJSON is an embedded relational document store built on top of pluggable key value storage\n\n    go get -u github.com/autom8ter/myjson\n\n- [Use Case](#use-case)\n- [Features:](#features-)\n  * [Architecture](#architecture)\n  * [Database](#database)\n  * [Storage Providers](#storage-providers)\n- [Getting Started](#getting-started)\n  * [Collection Schemas](#collection-schemas)\n    + [Custom Root Level Properties](#custom-root-level-properties)\n    + [Custom Field Level Properties](#custom-field-level-properties)\n    + [Example Schema](#example-schema)\n  * [Opening a database instance](#opening-a-database-instance)\n    + [Single Node in Memory (badger)](#single-node-in-memory--badger-)\n    + [Single Node w/ Persistance (badger)](#single-node-w--persistance--badger-)\n    + [Multi Node w/ Persistance (tikv)](#multi-node-w--persistance--tikv-)\n  * [Configuring a database instance](#configuring-a-database-instance)\n  * [Working with JSON documents](#working-with-json-documents)\n    + [Creating a JSON document](#creating-a-json-document)\n    + [Setting JSON values](#setting-json-values)\n    + [Getting JSON values](#getting-json-values)\n  * [Transactions](#transactions)\n    + [Writable](#writable)\n    + [Read Only](#read-only)\n    + [Adding documents to a collection](#adding-documents-to-a-collection)\n  * [Queries](#queries)\n    + [Joins](#joins)\n    + [Iterating through documents in a collection](#iterating-through-documents-in-a-collection)\n    + [Reading documents in a collection](#reading-documents-in-a-collection)\n  * [Change Streams](#change-streams)\n    + [Stream Changes in a given collection](#stream-changes-in-a-given-collection)\n  * [Aggregation](#aggregation)\n  * [Triggers](#triggers)\n  * [Scripts](#scripts)\n- [Tikv Setup Guide (full scale)](#tikv-setup-guide--full-scale-)\n- [Contributing](#contributing)\n\n## Use Case\n\nBuild powerful applications on top of simple key value storage. \n\n## Features:\n\n### Architecture\n\n| Feature                            | Description                                                                                    | Implemented |\n|------------------------------------|------------------------------------------------------------------------------------------------|-------------|\n| Single Node (in-memory)            | Run the embedded database with no persistance on a single node                                 | [x]         |\n| Single Node (on-disk)              | Run the embedded database with persistance on a single node                                    | [x]         |\n| Distributed (distributed kv-store) | Run the embedded database with horizontal scalability using tikv distributed key value storage | [x]         |\n\n### Database\n\n| Feature           | Description                                                                                                           | Implemented |\n|-------------------|-----------------------------------------------------------------------------------------------------------------------|-------------|\n| JSON Documents    | Records are stored as JSON documents                                                                                  | [x]         |\n| Collections       | Records are stored in Collections which can hold any number of JSON documents                                         | [x]         |\n| Collection Schema | Collections define a JSON Schema which enforces the schema of JSON documents in a collection                          | [x]         |\n| Transactions      | Cross Collection transactions can be used to persist/rollback changes to the database                                 | [x]         |\n| Change Streams    | Built in Change-Data-Capture collection can be queried \u0026 streamed for triggering realtime events                      | [x]         |\n| Scripting         | Javascript scripts can be executed with full access to database functionality                                         | [x]         |\n| Triggers          | Javascript triggers can be configured at the collection level to add custom business logic based on when events occur | [x]         |\n| Migrations        | Built in support for atomic database migrations written in javascript                                                 | [x]         |\n| Relationships     | Built in support for relationships with foreign keys - Joins and cascade deletes are also supported                   | [x]         |\n| Secondary Indexes | Multi-field secondary indexes may be used to boost query performance (eq/gt/lt/gte/lte)                               | [x]         |\n| Unique Fields     | Unique fields can be configured which ensure the uniqueness of a field value in a collection                          | [x]         |\n| Complex Queries   | Complex queries can be executed with support for select/where/join/having/orderby/groupby/limit/page clauses          | [x]         |\n| Aggregate Queries | Complex aggregate queries can be executed for analytical purposes                                                     | [x]         |\n| Time Travel       | Find the value of a   document at a specific timestamp                                                                | [x]         |\n| Revert            | Revert the value of a document to it's value at a specific timestamp                                                  | [x]         |\n\n### Storage Providers\n\n| Provider | Description                                           | Implemented |\n|----------|-------------------------------------------------------|-------------|\n| Badger   | persistant, embedded LSM database written in Go       | [x]         |\n| Tikv     | persistant, distributed LSM database  written in Rust | [x]         |\n| RocksDB  | persistant, embedded LSM database written in C++      |             |\n\n\n\n## Getting Started\n\n    go get -u github.com/autom8ter/myjson\n\nBefore getting started, take a look at the [examples](./examples) and [Godoc](https://godoc.org/github.com/autom8ter/myjson)\n\n### Collection Schemas\n\nCollection schemas are custom [JSON Schema](https://json-schema.org/) documents that declaratively configure a collection of documents. The\nschema defines the structure of the JSON documents in the collection and the constraints that\nshould be enforced on the documents. The schema is used to validate the documents in the collection\nand to enforce the constraints on the documents. The schema is also used to define secondary indexes,\nforeign keys, authorization, and triggers.\n\n#### Custom Root Level Properties\n\nMyJSON supports a number of custom root level properties that can be used to configure the schema of a collection.\n\n##### x-collection\n`x-collection` configures the unique name of the collection. The name of the collection must be unique across all collections in the database.\n`x-collection` is a required property.\n\n##### x-authorization\n`x-authorization` is a set of javascript authorization rules to enforce against actions taken against the database.\n`x-authorization` is an optional property.\n\n##### x-triggers\n`x-triggers` are a set of javascript triggers that execute when certain actions are taken against the database.\n`x-triggers` is an optional property.\n\n##### x-read-only\n`x-readonly` indicates that the collection is updated internally and may only be read.\n`x-readonly` is an optional property.\n\n##### x-prevent-deletes\n`x-prevent-deletes` indicates that documents in the collection may not be deleted.\n`x-prevent-deletes` is an optional property.\n\n##### x-immutable\n`x-immutable` indicates that documents in the collection may not be updated or deleted.\n\n#### Custom Field Level Properties\n\nMyJSON supports a number of custom field level properties that can be used to configure the schema of a collection.\n\n\n#### x-primary\n`x-primary` configures the documents primary key (exactly 1 field must specify x-primary).\nThe value of the field must be unique across all documents in the collection.\n\n#### x-foreign\n`x-foreign` configures a foreign key relationship. The value of the field must be the primary key of another document in the database.\nForeign keys are enforced by the database at runtime and boost query join performance.\n\n#### x-unique\n`x-unique` configures a unique field for the document. The value of the field must be unique across all documents in the collection.\na unique field is enforced by the database and is not configurable.\nFor example, if a document has a field called `_secondary_id` with `x-unique` set to true, then the value of the field\nmust be unique across all documents in the collection. Unique indexes also boost query performance.\n\n#### x-index\n`x-index` configures a secondary index. The value of the field is indexed and can be used to boost query performance.\nFor example, if a document has a field called `_secondary_id` with `x-index` set to true, then the value of the field\nwill be indexed and can be used to boost query performance.\n\n#### x-immutable\n`x-immutable` indicates that the field is immutable and all edits will be replaced with it's original value.\nFor example, if a document has a field called `_secondary_id` with `x-immutable` set to true, then the value of the field\nwill be set to it's permanent, immutable value on creattion. If the document is updated, the value of the field will\nnot be changed. Immutable properties override the `x-compute` and `default` properties.\n\n##### x-compute\n\n`x-compute` is a javascript expression that is evaluated when the document is created or updated. The expression\nis evaluated in the context of the document and the result is stored in the field. The expression is evaluated\nbefore the document is validated against the schema. The expression may be used to compute a value for a field\nbased on the values of other fields in the document. Computed properties override the `default` property.\n\n#### Example Schema\n\naccount.yaml\n```yaml\ntype: object\nx-collection: account\nrequired:\n  - _id\n  - name\nproperties:\n  _id:\n    type: string\n    description: The account's id.\n    x-primary: true\n  name:\n    type: string\n    description: The accounts's name.\nx-authorization:\n  rules:\n    ## allow super users to do anything\n    - effect: allow\n      ## match on any action\n      action:\n      - \"*\"\n      ## context metadata must have role super_user set to true\n      match: |\n        contains(meta.Get('roles'), 'super_user')\n\n      ## dont allow read-only users to create/update/delete/set accounts\n    - effect: deny\n      ## match on document mutations\n      action:\n        - create\n        - update\n        - delete\n        - set\n        ## context metadata must have a read_only role set to true\n      match: |\n        contains(meta.Get('roles'), 'read_only')\n\n      ## only allow users to update their own account\n    - effect: allow\n        ## match on document mutations\n      action:\n        - create\n        - update\n        - delete\n        - set\n        ## the account's _id must match the user's account_id\n      match: |\n        doc.Get('_id') == meta.Get('account_id')\n\n      ## only allow users to query their own account\n    - effect: allow\n        ## match on document queries (includes ForEach and other Query based methods)\n      action:\n        - query\n        ## user must have a group matching the account's _id\n      match: |\n        query.where?.length \u003e 0 \u0026\u0026 query.where[0].field == '_id' \u0026\u0026 query.where[0].op == 'eq' \u0026\u0026 contains(meta.Get('groups'), query.where[0].value)\n\n```\n\nuser.yaml\n\n```yaml\ntype: object\n# x-collection specifies the name of the collection the object will be stored in\nx-collection: user\n# required specifies the required attributes\nrequired:\n  - _id\n  - name\n  - age\n  - contact\n  - gender\n  - account_id\nproperties:\n  _id:\n    type: string\n    description: The user's id.\n    # x-primary indicates that the property is the primary key for the object - only one primary key may be specified\n    x-primary: true\n  name:\n    type: string\n    description: The user's name.\n  contact:\n    type: object\n    properties:\n      email:\n        type: string\n        description: The user's email.\n        `x-unique`: true\n  age:\n    description: Age in years which must be equal to or greater than zero.\n    type: integer\n    minimum: 0\n  account_id:\n    type: string\n    # x-foreign indicates that the property is a foreign key - foreign keys are automatically indexed\n    x-foreign:\n      collection: account\n      field: _id\n      cascade: true\n    # `x-index` specifies a secondary index which can have 1-many fields\n    `x-index`:\n      account_email_idx:\n        additional_fields:\n          - contact.email\n  language:\n    type: string\n    description: The user's first language.\n    `x-index`:\n      language_idx: { }\n  gender:\n    type: string\n    description: The user's gender.\n    enum:\n      - male\n      - female\n  timestamp:\n    type: string\n  annotations:\n    type: object\n\n# x-triggers are javascript functions that execute based on certain events\nx-triggers:\n  # name of the trigger\n  set_timestamp:\n    # order determines the order in which the functions are executed - lower ordered triggers are executed first\n    order: 1\n    # events configures the trigger to execute on certain events\n    events:\n      - on_create\n      - on_update\n      - on_set\n    # script is the javascript to execute\n    script: |\n      doc.Set('timestamp', new Date().toISOString())\n\n```\ntask.yaml\n\n```yaml\ntype: object\nx-collection: task\nrequired:\n  - _id\n  - user\n  - content\nproperties:\n  _id:\n    type: string\n    description: The user's id.\n    x-primary: true\n  user:\n    type: string\n    description: The id of the user who owns the task\n    x-foreign:\n      collection: user\n      field: _id\n      cascade: true\n  content:\n    type: string\n    description: The content of the task\n```\n\n\n#### Authorization \n\nTODO\n\n### Opening a database instance\n\n\n#### Single Node in Memory (badger)\n```go\ndb, err := myjson.Open(context.Background(), \"badger\", map[string]any{\n\t\"storage_path\": \"\",\n})\n```\n\n#### Single Node w/ Persistance (badger)\n```go\ndb, err := myjson.Open(context.Background(), \"badger\", map[string]any{\n\t\"storage_path\": \"./tmp\",\n})\n```\n\n\n#### Multi Node w/ Persistance (tikv)\n```go\ndb, err := myjson.Open(context.Background(), \"tikv\", map[string]any{\n    \"pd_addr\":    []string{\"http://pd0:2379\"},\n    \"redis_addr\": \"localhost:6379\",\n    \"redis_user\": \"admin\", //change me\n    \"redis_password\": \"123232\", //change me\n})\n```\n\n### Configuring a database instance\n\nCollection schemas can be configured at runtime or at startup. Collection schemas are declarative - \nany changes to indexing or validation happen within the database when Configure is called\n\n```go\n\nvar (\n    //go:embed account.yaml\n    accountSchema string\n    //go:embed user.yaml\n    userSchema string\n    //go:embed task.yaml\n    taskSchema string\n)\n\nif err := db.Configure(ctx, \"\", []string{accountSchema, userSchema, taskSchema}); err != nil {\n    panic(err)\n})\n```\n\n### Working with JSON documents\n\n#### Creating a JSON document\n\n```go\ndocument, err := myjson.NewDocumentFrom(map[string]any{\n    \"name\": \"acme.com\",\n})\n```\n\n```go\ndoc := myjson.NewDocument()\ndoc.Set(\"name\", \"acme.com\")\n```\n\n#### Setting JSON values\n\n```go\ndoc := myjson.NewDocument()\ndoc.Set(\"name\", \"acme.com\")\n```\n\nSJSON syntax is supported: https://github.com/tidwall/sjson#path-syntax\n```go\ndoc := myjson.NewDocument()\ndoc.Set(\"contact.email\", \"info@acme.com\")\n```\n\n\n#### Getting JSON values\n\n```go\ndoc := myjson.NewDocument()\ndoc.Set(\"name\", \"acme.com\")\n```\n\nGJSON syntax is supported: https://github.com/tidwall/sjson#path-syntax\n```go\nvalue := doc.Get(\"contact.email\")\n```\n\nadditional GJSON modifiers are available:\n- @camelCase - convert a json string field to camel case `doc.Get(\"project|@camelCase\")`\n- @snakeCase - convert a json string field to snake case `doc.Get(\"project|@snakeCase\")`\n- @kebabCase - convert a json string field to kebab case `doc.Get(\"project|@kebabCase\")`\n- @replaceAll - replace a substring within a json string field with another string \n- @unix - get the unix timestamp of the json time field `doc.Get(\"timestamp|@unix\")`\n- @unixMilli - get the unix millisecond timestamp of the json time field `doc.Get(\"timestamp|@unixMilli\")`\n- @unixNano - get the unix nanosecond timestamp of the json time field `doc.Get(\"timestamp|@unixNano\")`\n- @dateTrunc - truncate a date to day, month, or year ex: `doc.GetString(\"timestamp|@dateTrunc:month\")`,  `doc.GetString(\"timestamp|@dateTrunc:year\")`,  `doc.GetString(\"timestamp|@dateTrunc:day\")`\n\n### Transactions\n\nMost database functionality is made available via the Tx interface which has read/write methods\nacross 1-many collections.\n\n#### Writable\n```go\nif err := db.Tx(ctx, kv.TxOpts{IsReadOnly: false}, func(ctx context.Context, tx myjson.Tx) error {\n\t// do stuff ...tx.Set(...)\n\t// return error to rollback\n\t// return no error to commit\n}\n```\n\n#### Read Only\n\n```go\nif err := db.Tx(ctx, kv.TxOpts{IsReadOnly: true}, func(ctx context.Context, tx myjson.Tx) error {\n\t// ...tx.Get(...)\n}\n```\n\n#### Adding documents to a collection\n\n```go\nif err := db.Tx(ctx, kv.TxOpts{}, func(ctx context.Context, tx myjson.Tx) error {\n    doc := myjson.NewDocument()\n    doc.Set(\"name\", \"acme.com\")\n\tid, err := tx.Create(ctx, \"account\", document)\n\tif err != nil {\n\t\treturn err\n    }\n}\n```\n\n### Queries\n\n```go\nresults, err := tx.Query(ctx, \"user\", myjson.Q().\n    Select(myjson.Select{Field: \"*\"}).\n\tOrderBy(myjson.OrderBy{Field: \"age\", Direction: myjson.OrderByDirectionDesc}).\n    Query())\n```\n\n#### Joins\n\n1-many joins are \n```go\nresults, err := db.Query(ctx, \"user\", myjson.Q().\n    Select(\n        myjson.Select{Field: \"acc._id\", As: \"account_id\"},\n        myjson.Select{Field: \"acc.name\", As: \"account_name\"},\n\t\tmyjson.Select{Field: \"_id\", As: \"user_id\"},\n    ).\n    Join(myjson.Join{\n        Collection: \"account\",\n        On: []myjson.Where{\n            {\n\t\t\t\tField: \"_id\",\n\t\t\t\tOp:    myjson.WhereOpEq,\n                Value: \"$account_id\", //self reference the account_id on the user document\n            },\n    },\n        As: \"acc\",\n    }).\nQuery())\n```\n\n\n#### Iterating through documents in a collection\n\n```go\n_, err := tx.ForEach(ctx, \"user\", myjson.ForEachOpts{}, func(d *myjson.Document) (bool, error) {\n    fmt.Println(d)\n    return true, nil\n})\n```\n\n\n#### Reading documents in a collection\n\n```go\ndoc, err := tx.Get(ctx, \"user\", \"$id\")\n```\n\n### Change Streams\n\n#### Stream Changes in a given collection\n\nCDC persistance must be enabled for change streams to work. See the database Options for more info.\n\n```go\nctx, cancel := context.WithCancel(context.Background())\ndefer cancel()\nerr := db.ChangeStream(ctx, \"user\", func(cdc myjson.CDC) (bool, error) {\n    fmt.Println(cdc)\n    return true, nil\n})\n```\n\n### Aggregation\n\n```go\nquery := myjson.Query{\n\tSelect: []myjson.Select{\n\t\t{\n            Field: \"account_id\",\n\t\t},\n\t\t{\n            Field:     \"age\",\n            Aggregate: myjson.AggregateFunctionSum,\n            As:        \"age_sum\",\n\t\t},\n\t},\n\tGroupBy: []string{\"account_id\"},\n}\nresults, err := db.Query(ctx, \"user\", query)\n```\n\n### Triggers\n\nadd a triggers block to your JSON schema\nex: update timestamp on set/update/create with a javascript expression\n```yaml\ntriggers:\n  set_timestamp:\n    order: 1\n    events:\n      - on_create\n      - on_update\n      - on_set\n    script: |\n      doc.Set('timestamp', new Date().toISOString())\n```\n\njavascript variables are injected at runtime:\n- `doc` - the JSON document that is being changed\n- `db` - the global database instance(all methods are available)\n- `ctx` - the context when the trigger was called\n- `metadata` - the context metadata when the script is called\n- `tx` - the current transaction instance\n\n### Scripts\n\nScripts are javascript expressions/functions that can be called in Go - this may be used when embedded/dynamic functionality\nis required.\n\ngetAccountScript:\n```javascript\nfunction setAccount(ctx, db, params) {\n    db.tx(ctx, {isReadOnly: false}, (ctx, tx) =\u003e {\n        tx.set(ctx, \"account\", params.doc)\n    })\n}\n```\n\nexecute with custom paramaters:\n```go\nid := ksuid.New().String()\ndoc, err := myjson.NewDocumentFrom(map[string]any{\n    \"_id\":  id,\n    \"name\": gofakeit.Company(),\n})\n_, err = db.RunScript(ctx, \"setAccount\", getAccountScript, map[string]any{\n    \"doc\": doc,\n})\n```\njavascript variables are injected at runtime:\n- `db` - the global database instance(all methods are available lowercased)\n- `ctx` - the context when the script is called\n- `metadata` - the context metadata when the script is called\n- `newDocument` - function to intialize a new JSON document\n- `newDocumentFrom` - function to initialize a new JSON document from a javascript object\n\n## Tikv Setup Guide (full scale)\n\nWIP - see [tikv foldeer](kv/tikv) w/ Makefile for running tikv locally\n\n## Contributing\n\nInstall Dependencies\n\n    go mod download\n\nCheckout Branch\n\n    git checkout -b ${issueNumber}\n\nRun Tests\n\n    go test -race -covermode=atomic -coverprofile=coverage.out -v .\n\nRun Benchmarks\n\n    go test -bench=. -benchmem -run=^#\n\nLint Repository\n\n    golangci-lint run\n\nCheck Coverage\n\n    go tool cover -func=coverage.out\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fautom8ter%2Fmyjson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fautom8ter%2Fmyjson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fautom8ter%2Fmyjson/lists"}