Skip to content
This repository has been archived by the owner on Feb 15, 2021. It is now read-only.

Generate JSON-Schema #121

Open
mikemol opened this issue Dec 8, 2017 · 20 comments
Open

Generate JSON-Schema #121

mikemol opened this issue Dec 8, 2017 · 20 comments
Assignees
Labels
feature Something new.

Comments

@mikemol
Copy link

mikemol commented Dec 8, 2017

Does this support generating a JSON-Schema by inspecting an object and extracting its attributes as properties within a schema?

I.e. could I take an object, emit both a JSON representation of the object's value and a JSON-Schema representation of the object's structure, and use one to validate the other?

@gregsdennis
Copy link
Owner

At one point I had tried this, but I was having trouble with some types, like dictionaries. I'm open to exploring this again. It may be a while as I'm working over at the schema spec repo and some serialization performance enhancements.

@gregsdennis gregsdennis self-assigned this Dec 9, 2017
@gregsdennis gregsdennis added the feature Something new. label Dec 9, 2017
@gregsdennis
Copy link
Owner

gregsdennis commented Dec 14, 2017

@mikemol what features do you need for this? For example, do you expect it to place value restrictions (like min/max) on the properties?

I'm thinking that the client (you) could place attributes from the System.ComponentModel.DataAnnotations namespace. I already use DisplayAttribute for enum serialization, so I don't have to add a reference. The available validations are:

  • MinLength
  • MaxLength
  • Range
  • Required
  • StringLength (duplicates/combines MinLength & MaxLength)
  • EmailAddress
  • RegularExpression
  • Url

There isn't a built-in way to specify a schema for items in a list or dictionary, though.

Thoughts?


Also, my guess is that you then want to deserialize these into your objects, correct? If that's the case, you'll need to be sure the serializer is configured properly (which properties to serialize, etc.). For instance, a schema can validate a read-only property, but the serializer wouldn't be able to deserialize it (because it's read-only).

@gregsdennis
Copy link
Owner

These attributes don't cover all of the possibilities for schema. For example, there's no way to specify that a minimum is exclusive vs. inclusive.

May have to create a set of attributes for this.

@gregsdennis
Copy link
Owner

Just thinking out loud:

An argument against this feature might be that the schema types were designed to be easily created in code.

The response to this is that it creates duplication and maintenance of the model and the requirements in a multiple places. Whereas if I place attributes directly on my model and then generate the schema from that, I have all of my validation and model in one place.

@sixlettervariables
Copy link
Contributor

We use that approach in our Web API's via Swagger.Net. We generate a Swagger definition via convention+attributes and then use that to generate compatible clients.

Likewise if we had a convention+attribute model to generate schemas we could: (a) rapidly create schemas for existing models, and (b) extend our web services to publish their REST model schemas.

@gregsdennis
Copy link
Owner

I think I'm going to need to have the client provide a serializer for this. There are mechanics that the serializer is already set up to address:

  • property name transforms
  • enumeration serialization (both number and named, and considering the Display attribute)
  • property selection (read-only vs read/write vs write-only)

@gregsdennis
Copy link
Owner

gregsdennis commented Dec 15, 2017

See branch feature/issue-121-schema-generation

@sixlettervariables & @mikemol, please see SchemaGenerationTarget for an example of usage of things currently supported. The test that uses this is in the GenerationTest class.

I'd like your input on the public-facing side to see if this approach will support your needs.

@mikemol
Copy link
Author

mikemol commented Dec 15, 2017

I'll give it a go. Might take a bit. Had a hardware failure last night...

@gregsdennis
Copy link
Owner

I have made some additional improvements. I'm working on extracting common schemas into the root definitions collection.

@gregsdennis
Copy link
Owner

@mikemol I have a question about your preference for the output schema. The way I see it there are a couple options:

Repetition

Schemas for properties are simply defined at that property. If there is a property that has exactly the same type and restrictions, the schema is simply repeated for that property.

{
  "properties" : {
    "int1": { "type" : "integer", "maximum": 20 },
    "int2": { "type" : "integer", "maximum": 20 }
  }
}

Consolidation

The final schema is scanned for duplicates. The duplicates are then collected to be stored in the root's definitions collection and any usages are replaced by $refs.

{
  "definitions" : {
    "integer_max_20" : { "type" : "integer", "maximum": 20 }
  },
  "properties" : {
    "int1": { "$ref" : "#/definitions/integer_max_20" },
    "int2": { "$ref" : "#/definitions/integer_max_20" },
    "int3": { "type" : "integer", "minimum" : 10 }
  }
}

@sixlettervariables
Copy link
Contributor

I've been using the branch in my test setup, and had to make one change for it to work with our performance enhancements:

@@ -126,1 126,1 @@ Manatee.Json/Schema/Generation/SchemaGenerator.cs
-								  .Select(v => new EnumSchemaValue(((JsonValue)serializerMethod.Invoke(serializer, new[]{v})).String))
+								  .Select(v => new EnumSchemaValue(((JsonValue)serializerMethod.Invoke(serializer, v)).String))

It appears to work well for my needs (fairly simple).

@sixlettervariables
Copy link
Contributor

sixlettervariables commented Dec 29, 2017

I'd also enjoy a JsonSchemaFactory method to call GenerateFor using the default schema format (although not strictly required).

My usage of JsonSchema in our app's event system would be as follows:

  • Distributed Events have an ID and a JSON Payload (dictated by a schema)
  • Distributed Events are either built-in or ad-hoc
    • Built-in Events are defined with a well-known type
      • When a built-in event is registered, its JSON schema is generated from the type and stored
    • Ad-hoc Events are defined by an ID and JSON Schema combo
  • When events are received their JSON payload is checked against their schema
    • Event receivers can indicate if they want only good events, good events plus failures, or all events (with "bad" payloads)

I'm not savvy enough yet with JSON Schema, but eventually I'd need to add support for forwards/backwards compatibility in the automatically generated schemas.

@gregsdennis
Copy link
Owner

@sixlettervariables I'm building it with draft 7 for now. I'll update to support all drafts once I nail down the logic.

I'm not sure what you mean by "events" in this context. Can you elaborate?

@sixlettervariables
Copy link
Contributor

@gregsdennis just an example of how we're using JsonSchema in our application (i.e. part of a distributed events system).

@gregsdennis
Copy link
Owner

@mikemol any thoughts or preferences on the repitition/consolidation approaches I mentioned above?

@gregsdennis
Copy link
Owner

@mikemol @sixlettervariables any additional thoughts on this? It's a good feature. I don't want to see it stall out, but I think we need to nail down the desired behavior.

@gregsdennis
Copy link
Owner

Okay.... It's been a long time, but I think I need to get this done. I've also since rebuilt the schema implementation, and I failed to keep this branch up-to-date. That means that I have a lot of work to redo. 😢

@fgajtanovski
Copy link

Okay.... It's been a long time, but I think I need to get this done. I've also since rebuilt the schema implementation, and I failed to keep this branch up-to-date. That means that I have a lot of work to redo. 😢

Does the current library support generating json schema from c# object?

@gregsdennis
Copy link
Owner

Sadly no. I never got the chance to rewrite this. Life happens, you know. If there's enough interest, I might be able to find some time.

Repository owner deleted a comment from glikoz Jun 27, 2019
Repository owner deleted a comment from fgajtanovski Jun 27, 2019
Repository owner deleted a comment from glikoz Jun 27, 2019
@B1nke
Copy link

B1nke commented Apr 8, 2020

I would have loved this feature for a current project, but had to resort to doing schemas manually and just manipulating them with this lib.
One thing that I think could be really beneficial is that if you load your C# models with data in them and then generate the schema, it will actually take that into account and add for example oneOf/anyOf or similar for the data that is loaded, and it could be specified with an attribute.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature Something new.
Projects
None yet
Development

No branches or pull requests

5 participants