Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spurious subschema if there are doc comments #42

Closed
ahl opened this issue Jun 11, 2020 · 2 comments
Closed

spurious subschema if there are doc comments #42

ahl opened this issue Jun 11, 2020 · 2 comments

Comments

@ahl
Copy link
Contributor

ahl commented Jun 11, 2020

I noticed spurious SubschemaValidation.all_ofs with a single element being included. For example:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "B",
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "description": "doc comment",
      "allOf": [
        {
          "$ref": "#/definitions/Name"
        }
      ]
    }
  },
  "definitions": {
    "Name": {
      "type": "string"
    }
  }
}

I was able to narrow this down to a simple test case where the presence of a doc comment seems to trigger the behavior:

use schemars::schema_for;
use schemars::JsonSchema;

#[derive(JsonSchema)]
pub struct Name(String);

#[derive(JsonSchema)]
pub struct A {
    /** doc comment */
    pub name: Name,
}

#[derive(JsonSchema)]
pub struct B {
    /// doc comment
    pub name: Name,
}

#[derive(JsonSchema)]
pub struct C {
    // non-doc comment
    pub name: Name,
}

fn main() {
    let schema = schema_for!(A);
    println!("{}", serde_json::to_string_pretty(&schema).unwrap());
    let schema = schema_for!(B);
    println!("{}", serde_json::to_string_pretty(&schema).unwrap());
    let schema = schema_for!(C);
    println!("{}", serde_json::to_string_pretty(&schema).unwrap());
}

... which outputs:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "A",
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "description": "doc comment",
      "allOf": [
        {
          "$ref": "#/definitions/Name"
        }
      ]
    }
  },
  "definitions": {
    "Name": {
      "type": "string"
    }
  }
}
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "B",
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "description": "doc comment",
      "allOf": [
        {
          "$ref": "#/definitions/Name"
        }
      ]
    }
  },
  "definitions": {
    "Name": {
      "type": "string"
    }
  }
}
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "C",
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "$ref": "#/definitions/Name"
    }
  },
  "definitions": {
    "Name": {
      "type": "string"
    }
  }
}

Note that the C does not contain the allOf clause (and has no doc-comment).

I was able to reproduce this on 0.7.6 and 0.8.0-alpha-2.

I'm happy to fix this myself if you'd accept the PR.

@GREsau
Copy link
Owner

GREsau commented Jun 11, 2020

This is by-design. The schema_for macro generates schemas which conform to JSON Schema Draft 7, which does not allow an object with the $ref property to contain any other properties (see https://tools.ietf.org/html/draft-handrews-json-schema-01#section-8.3). So in order to include any other properties (including description), the $ref is wrapped in an allOf.

The newest JSON Schema specification (draft 2019-09) does not have this restriction. Schemars supports this, albeit in a more verbose way:

let schema = SchemaSettings::draft2019_09()
    .into_generator()
    .into_root_schema_for::<A>();
println!("{}", serde_json::to_string_pretty(&schema).unwrap());

Which would then output:

{
  "$schema": "https://json-schema.org/draft/2019-09/schema",
  "title": "A",
  "type": "object",
  "required": [
    "name"
  ],
  "properties": {
    "name": {
      "description": "doc comment",
      "$ref": "#/definitions/Name"
    }
  },
  "definitions": {
    "Name": {
      "type": "string"
    }
  }
}

@GREsau GREsau closed this as completed Jun 11, 2020
@ahl
Copy link
Contributor Author

ahl commented Jun 11, 2020

Thanks; sorry for the noise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants