4

I'm using Swagger with my ASP.NET Core application and for a HTTP POST endpoint returning Blog model:

[HttpPost]
[ProducesResponseType(typeof(Blog), StatusCodes.Status200OK)]
public IActionResult AddBlog([FromBody] string name)
{
    // Code removed for brevity...
    return Ok(newBlog);
}

Blog:

public Blog
{
    public int Id { get; set; }

    public string Name { get; set; }
}

Swagger in its UI will show example response for that endpoint:

{
  "Id": 0,
  "Name": "string"
}

What I'd like to do is to generate such example values in JSON for type of class I provide and where I need it, which is somewhere else in my application like:

var json = exampleValuesGenerator.Generate(typeof(Blog));

Is this possible?

Prolog
  • 2,698
  • 1
  • 18
  • 31
  • Do you want a string? – dariogriffo Jul 31 '20 at 12:26
  • No, I want full JSON generated from type. If the type has nested properties, I want the JSON to reflect that as well. – Prolog Jul 31 '20 at 12:28
  • A library like newtonsoft JSON will do the job, check my answer – dariogriffo Jul 31 '20 at 12:30
  • No, I don't want to **serialize existing object** to JSON. I want to **generate JSON** from type of an object with example values in properties. – Prolog Jul 31 '20 at 12:33
  • Hey. Do you want something like [this](https://github.com/mattfrear/Swashbuckle.AspNetCore.Filters#request-example)? – Morasiu Jul 31 '20 at 12:57
  • @Morasiu this looks like manual provider of example responses for Swagger. I want a generic generator. – Prolog Jul 31 '20 at 13:07
  • So you want a specific examples (better that swagger) but you don't want to write it by hand, right? – Morasiu Jul 31 '20 at 13:27
  • No, I want generic, not specific example values, just like Swagger does generate without any more information given. I want default values e.g. 0 for int. Swagger somehow knows it and generate values for all properties without hassle of configuring what should be in the example value. – Prolog Jul 31 '20 at 13:43
  • 1
    Do you mean [something like this](https://stackoverflow.com/a/51133923/113116) but for .NET? If there's no similar .NET library, you could try calling the Java library via [IKVM](http://www.ikvm.net/devguide/net2java.html). Or you could try using a [mock server](https://stackoverflow.com/q/38344711/113116) to generate sample responses. – Helen Jul 31 '20 at 16:41
  • 1
    Alternatively, [generate a JSON Schema](https://stackoverflow.com/q/15782982/113116) from your C# class, then [use a JSON Schema "sampler"](https://stackoverflow.com/q/45922832/113116) to generate sample JSON from that schema. – Helen Jul 31 '20 at 16:55
  • 1
    @Helen I think yes. Thank you for links and directions. Definitly will give it a try. And finally someone who understood what I'm asking about here :) – Prolog Jul 31 '20 at 16:58
  • If there are 10 people who don't understood the question you should probably rethink if you correctly stated what you requires. Downvoting an answer based on your poorly redacted question is also not good. You asked to generate values in JSON. You ended up thanking for being pointed out to generate a JSON schema. – dariogriffo Aug 01 '20 at 10:13
  • Polluting the site with low quality answer that clearly doesn't solve the problem stated isn't good as well. And by the way, I didn't downvote your answer because it's not wrong, it just doesn't solve my problem. I believe downvoting should be used only for potentially harmful answers. [This is](https://stackoverflow.com/questions/45922832/c-sharp-library-for-converting-json-schema-to-sample-json) what I wanted. – Prolog Aug 01 '20 at 10:37
  • @dariogriffo - The question here is pretty clear. OP wants to generate an EXAMPLE json from a given type. There are plenty of examples of how to generate a Json payload from an actual type. – Bronumski May 18 '21 at 13:58

4 Answers4

3

Closest I've come to the desired generator is by using a library NJsonSchema. Thanks to @Helen for giving me valuable directions to Json Schema. Usage example below:

public string Generate(Type type)
{
    return JsonSchema
        .FromType(type)
        .ToSampleJson()
        .ToString();
}

It isn't perfect though. For example, for model defined as follows:

public class User
{
    public string String { get; set; }
    public int Int { get; set; }
    public double Double { get; set; }
    public float Float { get; set; }
    public short Short { get; set; }
    public byte Byte { get; set; }
    public long Long { get; set; }
    public decimal Decimal { get; set; }
    public DateTime DateTime { get; set; }
    public TimeSpan TimeSpan { get; set; }
    public bool Bool { get; set; }
    public BindingFlags Enum2 { get; set; }
    public Blog NestedObject { get; set; }
    public Blog[] ArrayOfObjects { get; set; }
    public int[] ArrayOfValues { get; set; }
}

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
}

it generates a sample JSON:

{
  "String": "String",
  "Int": 0,
  "Double": 0,
  "Float": 0,
  "Short": 0,
  "Byte": 0,
  "Long": 0,
  "Decimal": 0,
  "DateTime": "2020-08-02T19:43:59.8759099+00:00",
  "TimeSpan": "TimeSpan",
  "Bool": false,
  "Enum2": 0,
  "NestedObject": null,
  "ArrayOfObjects": [
    {
      "Id": 0,
      "Name": "Name"
    }
  ],
  "ArrayOfValues": [
    0
  ]
}

Sadly NestedObject property is null when it shouldn't be and floating point types should have example value suggesting they are indeed floating type, not just 0 suggesting that they are of integer type. So yeah, it could be improved. But it's definitely better than nothing!

Prolog
  • 2,698
  • 1
  • 18
  • 31
  • Actually this does work for more complex objects but you need to decorate the properties with attributes like `Required` and `DefaultValue` on primitive objects. Additionally the `Description` attribute is used when generating the Json schema. – Bronumski May 18 '21 at 13:49
1

Yes, it's possible to generate such example values for responses and for POST request. For Get requests, it's difficult, see my question here: SwashBuckle Swagger-UI Example Request for HTTP GET Method with FromQuery Attribute

Have a look at the NuGet package Swashbuckle.AspNetCore.Filters:

You can define an example response such as this:

public class BlogExample : IExamplesProvider<Blog>
{
    public Blog GetExamples()
    {
        return new Blog()
        {
            Id = 123,
            Name = "John Smith"
        };
    }
}

SwaggerUI will then show these values instead of the empty default values.

citronas
  • 19,035
  • 27
  • 96
  • 164
  • I don't need to return specific example values, the defaults that Swagger generates are fine. But I would like to have a generic generator that would return example values for any type I provide via parameter (just as shown in an example usage in question), not only for those for which I would register IExamplesProvider. – Prolog Jul 31 '20 at 13:18
0

NJsonSchema is fine to generate the sample json for a CLR type:

var sampleJson = JsonSchema.FromType(typeof(Foo)).ToSampleJson().ToString();

Hoverer,if Foo has nested complex type as properties ,you have to add additional attribute such as [Required] to make things work.

As a result ,i prefer to combine AutoFixture with NJsonSchema to generate the sample json,here is the example:

[Fact]
public void Test1()
{
  var sampleJson = JsonConvert.SerializeObject(new Fixture().Create<Foo>());
  var str = JsonSchema.FromSampleJson(sampleJson).ToSampleJson();
  File.WriteAllText(Path.Combine(Path.GetTempPath(),Path.GetTempFileName()),str.ToString());
}
LoremIpsum
  • 1,652
  • 18
  • 27
-2

You can use any JSON library and serialise an empty object.

Using newtonsoft JSON

var json = JsonConvert.SerializeObject(new Blog());
dariogriffo
  • 4,148
  • 3
  • 17
  • 34