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

How to serialize generated schemas into JSON Schemas #149

Closed
joelhoisko opened this issue Aug 4, 2021 · 3 comments
Closed

How to serialize generated schemas into JSON Schemas #149

joelhoisko opened this issue Aug 4, 2021 · 3 comments
Labels
question Further information is requested

Comments

@joelhoisko
Copy link
Contributor

Environment

  • Nuget Package: JsonSchema.Net 1.10.7, JsonSchema.Net.Generation 1.8.0
  • Nuget Version: NuGet Command Line 5.10.0.7240
  • OS: Ubuntu 20.04
  • .Net Target: .Net 5

I've read through the docs, and I couldn't find an example on how to serialize the generated JsonSchema object into a JSON Schema string. Looking at the test I saw that using JsonSerializer.Serialize() seemed to be the way to go about it. But the resulting JSON isn't a schema at all. Maybe I'm missing something, or that using attributes is mandatory, but reading the docs I thought that it would actually make a schema with properties for me without using attributes (the docs do say "maybe", not sure what that then means).

Example:

using System;
using System.Text.Json;
using Json.Schema;
using Json.Schema.Generation;

namespace json_everything
{
    class Program
    {
        static void Main(string[] args)
        {
            var schema = new JsonSchemaBuilder().FromType(typeof(MyClass)).Build();
            var schemaJson = JsonSerializer.Serialize(schema, new JsonSerializerOptions { WriteIndented = true });
            Console.WriteLine(schemaJson);
        }
    }

    class MyClass
    {
        public MyClass(string myString)
        {
            MyString = myString;
        }
        public string MyString { get; }
    }
}

output:

{
  "type": "object"
}

I was expecting to get something like:

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

Is there a way to actually output a serialized JSON Schema from the JsonSchema class or am I missing something here?

@joelhoisko joelhoisko added the question Further information is requested label Aug 4, 2021
@joelhoisko
Copy link
Contributor Author

joelhoisko commented Aug 4, 2021

Changing the MyClass.MyString to also have a public setter made it a bit better:

class MyClass
{
    public MyClass(string myString)
    {
        MyString = myString;
    }
	// changed to public setter
    public string MyString { get; set; }
}

Output:

{
  "type": "object",
  "properties": {
    "MyString": {
      "type": "string"
    }
  }
}

I'd still expect it to have the "$schema" set to a version, and for the MyClass name to appear somewhere, but I'm not 100% how the serialization for type names works in JSON Schema.

So now I kinda assume that this is about the limitations of System.Text.Json serializer when it comes to immutable types. Guess I'm too used to using Newtonsoft and how it handles immutable types out of the box.

@gregsdennis
Copy link
Owner

gregsdennis commented Aug 4, 2021

It took me a bit to see it, but the generator uses read/write properties only. This matches current support of serialization. To get the readOnly or writeOnly keywords, you need to use the attributes.

For an example of this, you can see the tests.

[erases example of exactly what you just commented]


I designed it this way because the intent is that you'd generate the schemas from models that were intended as DTOs. Generally DTOs are read/write, not immutable. DTOs are then mapped to domain objects, which may or may not be immutable depending on your specific application requirements.

You're right on track with serializer support.

@gregsdennis
Copy link
Owner

I'm still working out how this should work, so I'm open to suggestions. Currently the attributes only work on properties, not class definitions, so I can't put a $schema or title on the top level. I'm not sure how I want that interaction to work exactly.

Still, as mentioned in the docs, this is designed to be a starting point for creating schemas. It's not intended as a direct-to-production solution. The JSON Schema team (of which I'm a part) has had many discussions on the viability of this, and we're not sufficiently confident in anyone's ability to generate a schema that is 100% ready for production use.

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

No branches or pull requests

2 participants