{"id":16490751,"url":"https://github.com/awinterman/api_object_specification","last_synced_at":"2025-07-13T12:35:40.991Z","repository":{"id":30246132,"uuid":"33797346","full_name":"AWinterman/api_object_specification","owner":"AWinterman","description":"A DSL for specifying API Objects, and a python module that creates a generator and parser from the spec.","archived":false,"fork":false,"pushed_at":"2021-04-14T23:41:01.000Z","size":85,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-11T20:34:31.003Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","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/AWinterman.png","metadata":{"files":{"readme":"README.rst","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}},"created_at":"2015-04-12T00:17:58.000Z","updated_at":"2021-04-14T23:41:01.000Z","dependencies_parsed_at":"2022-07-31T08:07:59.263Z","dependency_job_id":null,"html_url":"https://github.com/AWinterman/api_object_specification","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AWinterman%2Fapi_object_specification","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AWinterman%2Fapi_object_specification/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AWinterman%2Fapi_object_specification/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AWinterman%2Fapi_object_specification/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AWinterman","download_url":"https://codeload.github.com/AWinterman/api_object_specification/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241325943,"owners_count":19944475,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":[],"created_at":"2024-10-11T13:49:06.429Z","updated_at":"2025-03-01T06:23:26.490Z","avatar_url":"https://github.com/AWinterman.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"API Object Specification\n========================\n\n.. contents::\n\nOverview\n--------\n\nA DSL for writing specifications of JSON APIs, and an accompanying\nimplementation written in python. This package generates a parser and generator\nfor APIs defined by a spec file.\n\nWhy not just use a CFG?\n-----------------------\n\nCFGs are great! \n\nBut JSON APIs often have characteristics that don't match CFGs terribly well.\nThe DSL actually is a CFG with the following additional characteristics:\n\n- Includes the base JSON types as terminal symbols\n- Its JSON object keys are order insensitive: ``{\"foo\": 1, \"bar\": 2}`` matches\n  ``{\"bar\": 2, \"foo\": 1}`` (This is hard to do with a CFG)\n- Is whitespace insensitive (where appropriate).\n- Knows when to add and when not to add a comma.\n\nPerhaps more importantly, CFGs are not terribly easy to read.\n\nThis is awfully JSON specific!\n-------------------------------\n\nYou're right! I only write JSON APIs these days, but it doesn't seem\nunreasonable to extend the specification to support other formats in the\nfuture.\n\n\n.. _specification-format:\n\nSpecification Format \n--------------------\n\nToken Reference\n***************\n\nToken references look like ``\u003cNAME\u003e``, where ``NAME`` is any alphanumeric\nentry. The ``\u003c`` and ``\u003e`` symbols are configurable.\n\nEach TOKEN reference is replaced by the token definition, if it exists. If no\ndefinition exists, the resulting generator and parser classes will have\ncorresponding methods which throw ``NotImplemented`` exceptions.\n\nToken Definition\n****************\n\nToken definitions look like \n\n::\n\n  NAME: DEFINITION\n\nWhere the definition is a JSON blob containing token and non-token entries.\n\nName may be defined multiple times. The resulting specification accepts any\ndefinition of NAME.\n\nIf the content type of the api is JSON (configurable), then the following tokens are defined as primitives.\n\n- object\n- array\n- value\n- string\n- number\n- boolean\n\nExcepting boolean, which is either ``true`` or ``false``, their values are\ndefined at json.org.\n\nOptional Fields\n***************\n\nAt current, optional fields are supported simply by specifying two definitions\nfor the same token name:  For example:\n\n::\n\n        FOO_WRAPPER: {\n          \"foo\": \"bar\",\n          \"obj\": \u003cobject\u003e\n        }\n\n        FOO_WRAPPER: {\n          \"foo\": \"bar\",\n          \"array\": \u003carray\u003e\n        }\n\nRepeated Values\n***************\n\n``...``\n  The equivalent of the Kleane star-- the object must have zero or more\n  repetitions of the proceeding token.\n\n::\n\n      STRINGS: [\u003cstring\u003e... ]\n\nIf there must be at least two strings, then you can say\n\n::\n\n      STRINGS: [\u003cstring\u003e, \u003cstring\u003e, \u003cstring\u003e... ]\n\n\n\nLikewise, you can specify any number of keys of a certain type:\n\n::\n\n    FLEXIBLE: {\n      \u003cPAIRS\u003e...\n    }\n\n    PAIRS: \"narcissus\": \"man\"\n    PAIRS: \"echo\": \"nymph\"\n    PAIRS: \"zues\": \"god\"\n\nCommas will automatically be added where needed.\n\nImplementation\n--------------\n\nThe JSON parser and generator are implemented according to the following steps:\n\n1. Resolve replacement rules until we have a list of rules which consist of\n   only literals or terminal symbols. A terminal symbol is a token which either\n   has no definition, or whose definition is in terms of the primitives defined\n   above.\n2. Construct a list of keypath/terminal symbol pairs for each rule.\n3. Check or generate a value for each pair-- that is traverse the candidate\n   object according to the given keypath, and ensure that it matches the rule's\n   definition. The ``FLEXIBLE`` example above requires special casing-- the key\n   can match any of the possibilities defined by the replacement rule.\n4. If a regular expression operation rule is used, repeat step (3) until one of the following conditions has been met: \n\n   - We have exhausted the regular expression operator.\n   - The candidate object's entry at the keypath has been consumed.\n   - We generated a value a configurable maximum number of times.\n\n\nTo Do\n-----\n- Configuration documentation\n- API documentation\n- Write a generator which constructs objects according to the data structure described above.\n- Write a parser which is configured with the expectations data structure described above,\n  and takes json objects as input. It should either be a callable or have a method which returns true if an object conforms to\n  expectations, and false otherwise.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fawinterman%2Fapi_object_specification","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fawinterman%2Fapi_object_specification","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fawinterman%2Fapi_object_specification/lists"}