SolutionsCloud / apidoc

Api Documentation Generator
http://solutionscloud.github.io/apidoc/demo/
GNU General Public License v3.0
42 stars 10 forks source link

There's no way to make a property that's an arbitrary json object #15

Open radix opened 11 years ago

radix commented 11 years ago

I can't specify an API that has a JSON property which is an object of arbitrary keys and values.

"dynamic" is close, but it can only describe objects with homogeneous values. It would be nice if "dynamic" simply didn't require "items", allowing for arbitrary heterogeneous objects.

I'm confused that since apidoc apparently uses jsonschema in its implementation, that the description of properties isn't just directly jsonschema, which supports such arbitrary objects.

jderusse commented 11 years ago

Thank you for your contribution Christopher, I agree with you, ApiDoc should be closest to JSON Schema definitions, but when the project start, it doesn't used json-validator, it's a coincidence that the sources of ApiDoc looks like a JSON Schema. Anyway, I'am progressively moving the source for being compatible with JSON Schema. (ie: replace "optional" by "required", add "patternProperties", replace dynamic by "additionalProperties", replace type "enum" by property "enum", ...)

But I'am stuck with the representation of multiples types like "type": ["number", "string"] or multiple alternatives like "type": "object", "oneof": [{"properties":{...}}, {"properties":{...}}] (or allOf, anyOf, not...): which is what you want to do. right ?

IE: foo is a string: (basic case) OK

source (yaml)
foo:
  type: string

doc (json)
"foo": string

foo is an array of string (basic case) OK

source (yaml)
foo:
  type: array
  items:
    type: string

doc (json)
"foo": [
  string
]

foo is a string or a number

source (yaml)
foo:
  type:
  - string
  - number

doc (json)
"foo": ???

foo is an object allowing additional properties of number (a futur version of type dynamic) OK

source (yaml)
foo:
  type: object
  additionalProperties: 
    type: number

doc (json)
"foo": {
  string: number
}

foo is an object allowing additional properties of any type

source (yaml)
foo:
  type: object
  additionalProperties: true

doc (json)
"foo": {
  string: ??? (may be a keyword "ALL" or "*")
}

foo is an object allowing additional properties of different kind of objects (what you want right ?)

source (yaml)
foo:
  type: object
  additionalProperties:
    type: object
    oneOf:
    - properties:
        bar:
          type: string
    - properties:
        baz:
          type: string

doc (json)
"foo": {
  string: {
    ???
  }
}

Do you have suggestion on the cases which are not OK

note that your point is not only for object of arbitrary keys AND values even an arbitrary values with a known key is actualy not possible in ApiDoc :disappointed_relieved:

I hope we will find a proper way to render arbitraries values in ApiDoc, I'll try to include it in the next milestone (v1.2)

radix commented 11 years ago

I like the idea of converging on json-schema, and I think it answers all of your design questions.

First, to clarify, I don't want to use oneOf/anyOf/etc. My particular issue is solved in json-schema by a schema of {"type": "object"}.

As for the more general case, json-schema allows you to simply leave out the "type" keyword in any context, like

>>> jsonschema.validate("foo", {"$schema": "http://json-schema.org/draft-04/schema#"})

A schema with no "type" will match any object, so your "arbitrary values with a known key" question would be represented like this:

{"$schema": "http://json-schema.org/draft-04/schema#",
 "type": "object",
 "properties": {"a": {}},
 "required": ["a"]}

Personally I would like to just define an "object" with no "properties" in apidoc, to resolve my issue (if not just replacing the whole schema system with json-schema in yaml format).

By the way, in json-schema the use case for your "dynamic" object is solved with:

{"type": "object", "additionalProperties": {value_schema...}}
jderusse commented 11 years ago

To clarify a point, I would (progressively) migrate to JSON Schema for the yaml's sources. But the rendered documentation (in HTML) will stay as it is. ApiDoc is designed to display a clear and simple representation of an API. The JSON schema is really detailed, extendable and great for validation, but it's also realy verbose and hard to read.

JSON Schema
{
  "type": "object",
  "properties": {
  "a": {
    "type" : "string"
  }
}

ApiDoc representation
{
  "a": string
}

Anyway. I propose the following futur changes :

  1. Add patternProperties and additionalProperties in objects
  2. The object's property "properties" and array's property "items" are no longer required and can be empty.
  3. The property "type" is optional. When missing, ApiDoc will display the keyword "any" (like for "string", or "number"...)
  4. Add oneOf, anyOf, allOf, not: The differentes alteranative will be displayed separted by " xor ", " or ", " and ", " but "
  5. Allow array in types: will be rendered by ApiDoc like anyOf
radix commented 11 years ago

That sounds good to me!